परिचय

बार चार्ट में लेबल अक्सर पठनीयता की समस्याओं का सामना करते हैं जब चार्ट का आकार बदलता है, विभिन्न स्क्रीन रिज़ॉल्यूशंस पर प्रदर्शित होता है, या amCharts ज़ूम नियंत्रण का उपयोग करके ज़ूम इन/आउट किया जाता है। डिफ़ॉल्ट रूप से, amCharts 4 में लेबल की चौड़ाई निश्चित होती है, जो छोटे स्क्रीन पर ओवरलैपिंग, कटाव, या अपठनीय टेक्स्ट का कारण बन सकती है।

लेबल को वास्तव में प्रतिक्रियाशील बनाने के लिए, हमें:

  • चार्ट के आकार और कॉलम चौड़ाई के आधार पर लेबल की अधिकतम चौड़ाई को गतिशील रूप से गणना करें।
  • यदि आवश्यक हो तो लंबे लेबल को काटें ताकि ओवरफ्लो को रोका जा सके।
  • इवेंट हुक का उपयोग करें यह सुनिश्चित करने के लिए कि लेबल सही तरीके से समायोजित होते हैं जब:
    • चार्ट का आकार बदलता है।
    • ज़ूमिंग/पैनिंग होती है।
    • डेटा गतिशील रूप से अपडेट होता है।

इस लेख में, हम यह देखेंगे कि कैसे लेबल चौड़ाई को गतिशील रूप से समायोजित करें और आवश्यकतानुसार लेबल को काटें amCharts 4 इवेंट का उपयोग करके।

कॉलम चार्ट में ओवरलैपिंग लेबल और प्रतिक्रियाशीलता की कमी का एक उदाहरण

समस्या के साथ कार्यान्वयन कोड:


am4core.ready(function () {
    // Create the chart instance
    let chart = am4core.create("chartdiv", am4charts.XYChart);
    chart.hiddenState.properties.opacity = 0; // Initial fade-in
    chart.logo.disabled = true;
    chart.responsive.enabled = true; // Enable responsive behavior

    // Chart data
    chart.data = [
      { company: "Apple Inc.", visits: 23725 },
      { company: "Microsoft Corporation", visits: 1882 },
      { company: "Alphabet Inc. (Google)", visits: 1809 },
      { company: "Amazon.com, Inc.", visits: 1322 },
      { company: "Tesla, Inc.", visits: 1122 },
      { company: "Meta Platforms, Inc. (Facebook)", visits: 1114 },
      { company: "Berkshire Hathaway Inc.", visits: 711 },
      { company: "PepsiCo, Inc.", visits: 443 },
      { company: "Johnson & Johnson Services, Inc.", visits: 350 },
      { company: "McDonald's Corporation", visits: 298 },
      { company: "NVIDIA Corporation", visits: 150 },
      { company: "Netflix, Inc.", visits: 100 }
    ];

    // Create Category Axis (X-axis)
    let categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
    categoryAxis.dataFields.category = "company";
    categoryAxis.renderer.grid.template.location = 0;
    categoryAxis.renderer.minGridDistance = 40;
    categoryAxis.fontSize = 11;
    categoryAxis.renderer.labels.template.wrap = true;
    categoryAxis.renderer.labels.template.maxWidth = 80;
    categoryAxis.renderer.labels.template.padding(10, 0, 0, 0); // Set all sides to 0

    // Create Value Axis (Y-axis)
    let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
    valueAxis.min = 0;
    valueAxis.max = 24000;
    valueAxis.strictMinMax = true;
    valueAxis.renderer.minGridDistance = 30;

    // Create Column Series
    let series = chart.series.push(new am4charts.ColumnSeries());
    series.dataFields.categoryX = "company";
    series.dataFields.valueY = "visits";
    series.columns.template.tooltipText = "{valueY.value}";
    series.columns.template.tooltipY = 0;
    series.columns.template.strokeOpacity = 0;

    // Apply different colors to each column
    series.columns.template.adapter.add("fill", function (fill, target) {
      return chart.colors.getIndex(target.dataItem.index);
    });

    // Add Scrollbar
    chart.scrollbarX = new am4core.Scrollbar();
    chart.scrollbarX.marginTop = 30;
    chart.scrollbarX.parent = chart.bottomAxesContainer;

    // Add Axis Break for large values
    let axisBreak = valueAxis.axisBreaks.create();
    axisBreak.startValue = 2100;
    axisBreak.endValue = 22900;

    // Adjust Axis Break Size
    let d = (axisBreak.endValue - axisBreak.startValue) / (valueAxis.max - valueAxis.min);
    axisBreak.breakSize = 0.05 * (1 - d) / d; // Increased break size for better visibility

    // Adjust hover effect for better interaction
    let hoverState = axisBreak.states.create("hover");
    hoverState.properties.breakSize = 1; // Slightly larger break when hovered
    hoverState.properties.opacity = 0.1;
    hoverState.transitionDuration = 1500;

    axisBreak.defaultState.transitionDuration = 1000;

}); // end am4core.ready()

लेबल के लिए प्रतिक्रियाशील अधिकतम चौड़ाई सेट करना

एक कॉलम चार्ट में xAxis के लिए amCharts 4 में लेबल की एक निश्चित maxWidth होती है। हालाँकि, चूंकि यह चौड़ाई गतिशील रूप से समायोजित नहीं होती है, हमें इसे कॉलम चौड़ाई और चार्ट आकार के आधार पर गणना करनी चाहिए।

इस लक्ष्य को प्राप्त करने के लिए, हम rangechangeended और sizechanged इवेंट में हुक करते हैं, कॉलम की चौड़ाई की जांच करते हैं, और maxWidth को तदनुसार सेट करते हैं।

कार्यान्वयन

// Function to update label max width based on the widest column
const updateLabelMaxWidth = () => {
  let maxColumnWidth = 0;

  // Loop through each column and find the maximum width
  series.columns.each(function (column) {
    if (column && column.pixelWidth > maxColumnWidth) {
      maxColumnWidth = column.pixelWidth;
    }
  });

  // Apply max width to labels
  categoryAxis.renderer.labels.template.maxWidth = maxColumnWidth;
  console.log("Updated Max Label Width: " + maxColumnWidth);

  // Force label to be reprocessed
  categoryAxis.invalidateLabels();
}

// Trigger label width update on zoom/pan
categoryAxis.events.on("rangechangeended", function () {
  updateLabelMaxWidth();
});

// Trigger label width update on screen resize
chart.events.on("sizechanged", function () {
  updateLabelMaxWidth();
});

व्याख्या

फंक्शन updateLabelMaxWidth चार्ट में सबसे चौड़े कॉलम के आधार पर x-axis लेबल की चौड़ाई को गतिशील रूप से समायोजित करता है। यह सभी कॉलम के माध्यम से लूप करता है, अधिकतम चौड़ाई को ढूंढता है, और ओवरलैपिंग को रोकने के लिए लेबल पर लागू करता है।

इवेंट हुक:

  • rangechangeended → ज़ूमिंग/पैनिंग करते समय लेबल चौड़ाई को अपडेट करता है।
  • sizechanged → चार्ट का आकार बदलने पर लेबल को समायोजित करता है।

यह सुनिश्चित करता है कि लेबल गतिशील रूप से आकार बदलते हैं उपलब्ध स्थान के आधार पर।

बेहतर पठनीयता के लिए लंबे लेबल को काटना

गतिशील अधिकतम चौड़ाई के साथ भी, कुछ लेबल अभी भी बहुत लंबे हो सकते हैं और अव्यवस्था का कारण बन सकते हैं। इसे संभालने के लिए, हम लेबल को काटते हैं जब वे एक निश्चित लंबाई से अधिक हो जाते हैं।

कार्यान्वयन

categoryAxis.renderer.labels.template.adapter.add("textOutput", function(text, target) {
    let maxLabelLength = 10; // Set the maximum number of characters before truncation

    if (text.length > maxLabelLength) {
        return text.substring(0, maxLabelLength) + "..."; // Truncate and add ellipsis
    }
    return text; // Return original text if it's within the limit
});

व्याख्या

  • यह फ़ंक्शन प्रत्येक लेबल की लंबाई की जांच करता है।
  • यदि लेबल बहुत लंबा है, तो यह टेक्स्ट को पहले शब्द तक काटता है और अंत में ".." जोड़ता है।
  • जो लेबल अधिकतम वर्ण सीमा के भीतर हैं, वे अपरिवर्तित रहते हैं।

यह सुनिश्चित करता है कि लंबे लेबल ओवरलैप न हों जबकि अभी भी पर्याप्त जानकारी प्रदान करते हैं और आकार बदलने या ज़ूम इन/आउट करने पर प्रतिक्रियाशील रहते हैं।

गतिशील लेबल समायोजन लागू करने के बाद अंतिम परिणाम

समाधान लागू करने के बाद पूरा कार्यान्वयन कोड


am4core.ready(function () {
  // Create the chart instance
  let chart = am4core.create("chartdiv", am4charts.XYChart);
  chart.hiddenState.properties.opacity = 0; // Initial fade-in
  chart.logo.disabled = true;
  chart.responsive.enabled = true; // Enable responsive behavior

  // Chart data
  chart.data = [
    { company: "Apple Inc.", visits: 23725 },
    { company: "Microsoft Corporation", visits: 1882 },
    { company: "Alphabet Inc. (Google)", visits: 1809 },
    { company: "Amazon.com, Inc.", visits: 1322 },
    { company: "Tesla, Inc.", visits: 1122 },
    { company: "Meta Platforms, Inc. (Facebook)", visits: 1114 },
    { company: "Berkshire Hathaway Inc.", visits: 711 },
    { company: "PepsiCo, Inc.", visits: 443 },
    { company: "Johnson & Johnson Services, Inc.", visits: 350 },
    { company: "McDonald's Corporation", visits: 298 },
    { company: "NVIDIA Corporation", visits: 150 },
    { company: "Netflix, Inc.", visits: 100 }
  ];

  // Create Category Axis (X-axis)
  let categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
  categoryAxis.dataFields.category = "company";
  categoryAxis.renderer.grid.template.location = 0;
  categoryAxis.renderer.minGridDistance = 40;
  categoryAxis.fontSize = 11;
  categoryAxis.renderer.labels.template.wrap = true;
  categoryAxis.renderer.labels.template.maxWidth = 80;
  categoryAxis.renderer.labels.template.padding(10, 0, 0, 0); // Set all sides to 0

  // Create Value Axis (Y-axis)
  let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
  valueAxis.min = 0;
  valueAxis.max = 24000;
  valueAxis.strictMinMax = true;
  valueAxis.renderer.minGridDistance = 30;

  // Function to update label max width based on the widest column
  const updateLabelMaxWidth = () => {
    let maxColumnWidth = 0;

    // Loop through each column and find the maximum width
    series.columns.each(function (column) {
      if (column && column.pixelWidth > maxColumnWidth) {
        maxColumnWidth = column.pixelWidth;
      }
    });

    // Apply max width to labels
    categoryAxis.renderer.labels.template.maxWidth = maxColumnWidth;
    console.log("Updated Max Label Width: " + maxColumnWidth);

    // Force label to be reprocessed
    categoryAxis.invalidateLabels();
  }

  // Trigger label width update on zoom/pan
  categoryAxis.events.on("rangechangeended", function () {
    updateLabelMaxWidth();
  });

  // Trigger label width update on screen resize
  chart.events.on("sizechanged", function () {
    updateLabelMaxWidth();
  });

  // Truncate labels at the end of the first word when necessary
  categoryAxis.renderer.labels.template.adapter.add("textOutput", function (text, target) {
    let labelMaxWidth = target.maxWidth;

    if (labelMaxWidth < 60 && text) { // Check if label width is less than 60 pixels
      let words = text.split(" "); // Split text into words
      return words.length > 1 ? words[0] + ".." : text; // Keep only the first word with ".."
    }

    return text;
  });

  // Create Column Series
  let series = chart.series.push(new am4charts.ColumnSeries());
  series.dataFields.categoryX = "company";
  series.dataFields.valueY = "visits";
  series.columns.template.tooltipText = "{valueY.value}";
  series.columns.template.tooltipY = 0;
  series.columns.template.strokeOpacity = 0;

  // Apply different colors to each column
  series.columns.template.adapter.add("fill", function (fill, target) {
    return chart.colors.getIndex(target.dataItem.index);
  });

  // Add Scrollbar
  chart.scrollbarX = new am4core.Scrollbar();
  chart.scrollbarX.marginTop = 30;
  chart.scrollbarX.parent = chart.bottomAxesContainer;

  // Add Axis Break for large values
  let axisBreak = valueAxis.axisBreaks.create();
  axisBreak.startValue = 2100;
  axisBreak.endValue = 22900;

  // Adjust Axis Break Size
  let d = (axisBreak.endValue - axisBreak.startValue) / (valueAxis.max - valueAxis.min);
  axisBreak.breakSize = 0.05 * (1 - d) / d; // Increased break size for better visibility

  // Adjust hover effect for better interaction
  let hoverState = axisBreak.states.create("hover");
  hoverState.properties.breakSize = 1; // Slightly larger break when hovered
  hoverState.properties.opacity = 0.1;
  hoverState.transitionDuration = 1500;

  axisBreak.defaultState.transitionDuration = 1000;

}); // end am4core.ready()

इन समायोजनों के साथ, हमारा चार्ट अब पूर्णता से अनुकूलित है—लेबल पठनीय रहते हैं, कोई और बदसूरत ओवरलैप नहीं, और सब कुछ सुचारू रूप से आकार बदलता है। चौड़ाई को गतिशील रूप से समायोजित करके, लंबे नामों को काटकर, और इवेंट्स में हुक करके, हमने सुनिश्चित किया है कि चार्ट किसी भी स्क्रीन पर शानदार दिखता है। अब, आगे बढ़ें और इसे आजमाएं!