Einführung
Beschriftungen in Säulendiagrammen haben oft Lesbarkeitsprobleme, wenn das Diagramm verkleinert, auf verschiedenen Bildschirmauflösungen angezeigt oder mit den Zoom-Steuerelementen von amCharts hinein- oder herausgezoomt wird. Standardmäßig haben Beschriftungen in amCharts 4 eine feste Breite, was zu Überlappungen, Abschneidungen oder unleserlichem Text auf kleinen Bildschirmen führen kann.
Um Beschriftungen wirklich responsive zu gestalten, müssen wir:
- Die maximale Breite der Beschriftungen dynamisch basierend auf der Diagrammgröße und der Säulenbreite berechnen.
- Lange Beschriftungen bei Bedarf abschneiden, um Überlauf zu verhindern.
- Verwenden Sie Ereignis-Hooks, um sicherzustellen, dass die Beschriftungen richtig angepasst werden, wenn:
- Das Diagramm wird neu dimensioniert.
- Zoom/Panning erfolgt.
- Daten werden dynamisch aktualisiert.
In diesem Artikel werden wir untersuchen, wie man die Beschriftungsbreite dynamisch anpasst und Beschriftungen bei Bedarf abschneidet mithilfe von amCharts 4-Ereignissen.
Implementierungscode mit dem Problem:
am4core.ready(function () {
// Erstellen Sie die Diagramminstanz
let chart = am4core.create("chartdiv", am4charts.XYChart);
chart.hiddenState.properties.opacity = 0; // Anfangs einblenden
chart.logo.disabled = true;
chart.responsive.enabled = true; // Reaktionsfähigkeit aktivieren
// Diagrammdaten
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 }
];
// Erstellen Sie die Kategoriewachse (X-Achse)
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); // Alle Seiten auf 0 setzen
// Erstellen Sie die Wertachse (Y-Achse)
let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.min = 0;
valueAxis.max = 24000;
valueAxis.strictMinMax = true;
valueAxis.renderer.minGridDistance = 30;
// Erstellen Sie die Säulensammlung
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;
// Wenden Sie unterschiedliche Farben auf jede Säule an
series.columns.template.adapter.add("fill", function (fill, target) {
return chart.colors.getIndex(target.dataItem.index);
});
// Fügen Sie eine Bildlaufleiste hinzu
chart.scrollbarX = new am4core.Scrollbar();
chart.scrollbarX.marginTop = 30;
chart.scrollbarX.parent = chart.bottomAxesContainer;
// Fügen Sie eine Achsenunterbrechung für große Werte hinzu
let axisBreak = valueAxis.axisBreaks.create();
axisBreak.startValue = 2100;
axisBreak.endValue = 22900;
// Passen Sie die Größe der Achsenunterbrechung an
let d = (axisBreak.endValue - axisBreak.startValue) / (valueAxis.max - valueAxis.min);
axisBreak.breakSize = 0.05 * (1 - d) / d; // Erhöhte Unterbrechungsgröße für bessere Sichtbarkeit
// Passen Sie den Hover-Effekt für bessere Interaktion an
let hoverState = axisBreak.states.create("hover");
hoverState.properties.breakSize = 1; // Etwas größere Unterbrechung beim Hover
hoverState.properties.opacity = 0.1;
hoverState.transitionDuration = 1500;
axisBreak.defaultState.transitionDuration = 1000;
}); // Ende am4core.ready()
Einstellen einer responsiven maximalen Breite für Beschriftungen
In amCharts 4 haben Beschriftungen für die xAxis in einem Säulendiagramm eine feste maxWidth. Da diese Breite jedoch nicht dynamisch angepasst wird, müssen wir sie basierend auf der Säulenbreite und der Diagrammgröße berechnen.
Um dies zu erreichen, greifen wir auf das rangechangeended und sizechanged Ereignis zu, überprüfen die Breite der Säulen und setzen die maxWidth entsprechend.
Implementierung
// Funktion zur Aktualisierung der maximalen Breite der Beschriftung basierend auf der breitesten Säule
const updateLabelMaxWidth = () => {
let maxColumnWidth = 0;
// Durchlaufen Sie jede Säule und finden Sie die maximale Breite
series.columns.each(function (column) {
if (column && column.pixelWidth > maxColumnWidth) {
maxColumnWidth = column.pixelWidth;
}
});
// Wenden Sie die maximale Breite auf die Beschriftungen an
categoryAxis.renderer.labels.template.maxWidth = maxColumnWidth;
console.log("Aktualisierte maximale Beschriftungsbreite: " + maxColumnWidth);
// Zwingen Sie die Beschriftung zur Neuberechnung
categoryAxis.invalidateLabels();
}
// Auslösen der Aktualisierung der Beschriftungsbreite beim Zoom/Pan
categoryAxis.events.on("rangechangeended", function () {
updateLabelMaxWidth();
});
// Auslösen der Aktualisierung der Beschriftungsbreite bei Bildschirmänderung
chart.events.on("sizechanged", function () {
updateLabelMaxWidth();
});
Erläuterung
Die Funktion updateLabelMaxWidth passt die Breite der x-Achsenbeschriftungen dynamisch basierend auf der breitesten Säule im Diagramm an. Sie durchläuft alle Säulen, findet die maximale Breite und wendet sie auf die Beschriftungen an, um Überlappungen zu verhindern.
Ereignis-Hooks:
- rangechangeended → Aktualisiert die Beschriftungsbreite beim Zoom/Pan.
- sizechanged → Passt die Beschriftungen an, wenn das Diagramm neu dimensioniert wird.
Dies stellt sicher, dass die Beschriftungen dynamisch skaliert werden basierend auf dem verfügbaren Platz.
Lange Beschriftungen für bessere Lesbarkeit abschneiden
Selbst mit einer dynamischen maximalen Breite können einige Beschriftungen immer noch zu lang sein und Unordnung verursachen. Um dies zu handhaben, schneiden wir Beschriftungen ab, wenn sie eine bestimmte Länge überschreiten.
Implementierung
categoryAxis.renderer.labels.template.adapter.add("textOutput", function(text, target) {
let maxLabelLength = 10; // Setzen Sie die maximale Anzahl von Zeichen vor dem Abschneiden
if (text.length > maxLabelLength) {
return text.substring(0, maxLabelLength) + "..."; // Abschneiden und Ellipse hinzufügen
}
return text; // Ursprünglichen Text zurückgeben, wenn er innerhalb des Limits liegt
});
Erläuterung
- Diese Funktion prüft die Länge jeder Beschriftung.
- Wenn die Beschriftung zu lang ist, wird der Text auf das erste Wort gekürzt und ".." am Ende hinzugefügt.
- Beschriftungen innerhalb des maximalen Zeichenlimits bleiben unverändert.
Dies stellt sicher, dass lange Beschriftungen sich nicht überlappen, während sie dennoch genügend Informationen bieten und bei Größenänderungen oder Zoomvorgängen reaktionsfähig bleiben.
Vollständiger Implementierungscode nach Anwendung der Lösung
am4core.ready(function () {
// Erstellen Sie die Diagramminstanz
let chart = am4core.create("chartdiv", am4charts.XYChart);
chart.hiddenState.properties.opacity = 0; // Anfangs einblenden
chart.logo.disabled = true;
chart.responsive.enabled = true; // Reaktionsfähigkeit aktivieren
// Diagrammdaten
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 }
];
// Erstellen Sie die Kategoriewachse (X-Achse)
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); // Alle Seiten auf 0 setzen
// Erstellen Sie die Wertachse (Y-Achse)
let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.min = 0;
valueAxis.max = 24000;
valueAxis.strictMinMax = true;
valueAxis.renderer.minGridDistance = 30;
// Funktion zur Aktualisierung der maximalen Breite der Beschriftung basierend auf der breitesten Säule
const updateLabelMaxWidth = () => {
let maxColumnWidth = 0;
// Durchlaufen Sie jede Säule und finden Sie die maximale Breite
series.columns.each(function (column) {
if (column && column.pixelWidth > maxColumnWidth) {
maxColumnWidth = column.pixelWidth;
}
});
// Wenden Sie die maximale Breite auf die Beschriftungen an
categoryAxis.renderer.labels.template.maxWidth = maxColumnWidth;
console.log("Aktualisierte maximale Beschriftungsbreite: " + maxColumnWidth);
// Zwingen Sie die Beschriftung zur Neuberechnung
categoryAxis.invalidateLabels();
}
// Auslösen der Aktualisierung der Beschriftungsbreite beim Zoom/Pan
categoryAxis.events.on("rangechangeended", function () {
updateLabelMaxWidth();
});
// Auslösen der Aktualisierung der Beschriftungsbreite bei Bildschirmänderung
chart.events.on("sizechanged", function () {
updateLabelMaxWidth();
});
// Beschriftungen am Ende des ersten Wortes bei Bedarf abschneiden
categoryAxis.renderer.labels.template.adapter.add("textOutput", function (text, target) {
let labelMaxWidth = target.maxWidth;
if (labelMaxWidth < 60 && text) { // Überprüfen, ob die Beschriftungsbreite weniger als 60 Pixel beträgt
let words = text.split(" "); // Text in Wörter aufteilen
return words.length > 1 ? words[0] + ".." : text; // Nur das erste Wort mit ".." behalten
}
return text;
});
// Erstellen Sie die Säulensammlung
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;
// Wenden Sie unterschiedliche Farben auf jede Säule an
series.columns.template.adapter.add("fill", function (fill, target) {
return chart.colors.getIndex(target.dataItem.index);
});
// Fügen Sie eine Bildlaufleiste hinzu
chart.scrollbarX = new am4core.Scrollbar();
chart.scrollbarX.marginTop = 30;
chart.scrollbarX.parent = chart.bottomAxesContainer;
// Fügen Sie eine Achsenunterbrechung für große Werte hinzu
let axisBreak = valueAxis.axisBreaks.create();
axisBreak.startValue = 2100;
axisBreak.endValue = 22900;
// Passen Sie die Größe der Achsenunterbrechung an
let d = (axisBreak.endValue - axisBreak.startValue) / (valueAxis.max - valueAxis.min);
axisBreak.breakSize = 0.05 * (1 - d) / d; // Erhöhte Unterbrechungsgröße für bessere Sichtbarkeit
// Passen Sie den Hover-Effekt für bessere Interaktion an
let hoverState = axisBreak.states.create("hover");
hoverState.properties.breakSize = 1; // Etwas größere Unterbrechung beim Hover
hoverState.properties.opacity = 0.1;
hoverState.transitionDuration = 1500;
axisBreak.defaultState.transitionDuration = 1000;
}); // Ende am4core.ready()
Mit diesen Anpassungen passt sich unser Diagramm nun perfekt an—die Beschriftungen bleiben lesbar, keine hässlichen Überlappungen mehr, und alles wird reibungslos skaliert. Durch die dynamische Anpassung der Breiten, das Abschneiden langer Namen und das Einbinden von Ereignissen haben wir sichergestellt, dass das Diagramm auf jedem Bildschirm großartig aussieht. Probieren Sie es jetzt aus!