Adaptively-rounded corners on mixed column stacks
This demo shows how adapters can be used to apply custom fuzzy logic to rounded corners on column stacks.
/** * --------------------------------------- * This demo was created using amCharts 5. * * For more information visit: * https://www.amcharts.com/ * * Documentation is available at: * https://www.amcharts.com/docs/v5/ * --------------------------------------- */
// Create root element// https://www.amcharts.com/docs/v5/getting-started/#Root_elementvar root = am5.Root.new("chartdiv");
// Set themes// https://www.amcharts.com/docs/v5/concepts/themes/root.setThemes([am5themes_Animated.new(root)]);
// Create chart// https://www.amcharts.com/docs/v5/charts/xy-chart/var chart = root.container.children.push( am5xy.XYChart.new(root, { panX: false, panY: false, wheelX: "panX", wheelY: "zoomX", layout: root.verticalLayout }));
// Add legend// https://www.amcharts.com/docs/v5/charts/xy-chart/legend-xy-series/var legend = chart.children.push( am5.Legend.new(root, { centerX: am5.p50, x: am5.p50 }));
var data = [ { year: "2021", europe: 0.5, namerica: 0.9, asia: 2.1 }, { year: "2022", europe: 0.6, //namerica: 0.6, asia: 2.2 }, { year: "2023", europe: 0.8, namerica: 1.9, asia: 2.4 }];
// Create axes// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/var xAxis = chart.xAxes.push( am5xy.CategoryAxis.new(root, { categoryField: "year", renderer: am5xy.AxisRendererX.new(root, { cellStartLocation: 0.1, cellEndLocation: 0.9 }),
tooltip: am5.Tooltip.new(root, {}) }));
xAxis.data.setAll(data);
var yAxis = chart.yAxes.push( am5xy.ValueAxis.new(root, { calculateTotals: true, renderer: am5xy.AxisRendererY.new(root, {}) }));
// Add series// https://www.amcharts.com/docs/v5/charts/xy-chart/series/function makeSeries(name, fieldName, stacked, position) { var series = chart.series.push( am5xy.ColumnSeries.new(root, { name: name, xAxis: xAxis, yAxis: yAxis, valueYField: fieldName, categoryXField: "year", stacked: stacked }) );
series.columns.template.setAll({ tooltipText: "{name}, {categoryX}:{valueY}", width: am5.p100, tooltipY: 0, cornerRadiusTL: 0, cornerRadiusTR: 0, cornerRadiusBL: 0, cornerRadiusBR: 0 });
// Handle top corners series.columns.template.adapters.add("cornerRadiusTL", function (radius, target) { return isTop(target.dataItem) ? 10 : 0; }); series.columns.template.adapters.add("cornerRadiusTR", function (radius, target) { return isTop(target.dataItem) ? 10 : 0; });
function getCategoryDataItems(dataItem) { var targetSeries = dataItem.component; var currentStack = false; var index = xAxis.categoryToIndex(dataItem.get("categoryX")); var items = []; chart.series.each(function (series) { if (!series.get("stacked")) { if (currentStack) { return items; } else { items = []; } } if (series == targetSeries) { currentStack = true; } if (series.get("visible")) { items.push(series.dataItems[index]); } }); return items; }
// Handle bottom corners var bottomSetting = ""; if (position == "left") { bottomSetting = "cornerRadiusBL"; } else if (position == "right") { bottomSetting = "cornerRadiusBR"; }
if (bottomSetting != "") { series.columns.template.adapters.add(bottomSetting, function (radius, target) { return isBottom(target.dataItem) ? 10 : 0; }); }
// Corner handling functions function isBottom(dataItem) { var items = getCategoryDataItems(dataItem); var targetBottom = 0; var maxBottom = 0; am5.array.each(items, function (item) { var bottom = item.get("bottom"); if (item === dataItem) { targetBottom = bottom; } if (maxBottom < bottom) { maxBottom = bottom; } }); return targetBottom == maxBottom; }
function isTop(dataItem) { var items = getCategoryDataItems(dataItem); var targetTop = 0; var maxTop = 100000; am5.array.each(items, function (item) { var top = item.get("top"); if (item === dataItem) { targetTop = top; } if (maxTop > top) { maxTop = top; } }); return targetTop == maxTop; }
series.bullets.push(function () { return am5.Bullet.new(root, { locationY: 0.5, sprite: am5.Label.new(root, { text: "{valueY}", fill: root.interfaceColors.get("alternativeText"), centerY: am5.p50, centerX: am5.p50, populateText: true, oversizedBehavior: "hide" }) }); });
series.data.setAll(data); series.appear(); legend.data.push(series);}
makeSeries("Europe", "europe", true, "left");makeSeries("North America", "namerica", true, "left");makeSeries("Asia", "asia", false, "right");
// Make stuff animate on load// https://www.amcharts.com/docs/v5/concepts/animations/chart.appear(1000, 100);<div id="chartdiv"></div>body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";}
#chartdiv { width: 100%; height: 98vh;}{ "type": "XYChart", "settings": { "panX": false, "panY": false, "wheelX": "panX", "wheelY": "zoomX", "layout": { "type": "VerticalLayout" } }, "properties": { "series": [ "#series-0", "#series-1", "#series-2" ], "xAxes": [ "#axis-0" ], "yAxes": [ "#axis-1" ] }, "children": [ { "type": "Legend", "settings": { "centerX": { "type": "Percent", "value": 50 }, "x": { "type": "Percent", "value": 50 } }, "properties": { "data": [ "#series-0", "#series-1", "#series-2" ] } } ], "refs": [ { "data-0": [ { "year": "2021", "europe": 0.5, "namerica": 0.9, "asia": 2.1 }, { "year": "2022", "europe": 0.6, "asia": 2.2 }, { "year": "2023", "europe": 0.8, "namerica": 1.9, "asia": 2.4 } ] }, { "axis-0": { "type": "CategoryAxis", "settings": { "categoryField": "year", "renderer": { "type": "AxisRendererX", "settings": { "cellStartLocation": 0.1, "cellEndLocation": 0.9 } }, "tooltip": { "type": "Tooltip" } }, "properties": { "data": "#data-0" } } }, { "axis-1": { "type": "ValueAxis", "settings": { "calculateTotals": true, "renderer": { "type": "AxisRendererY" } } } }, { "series-0": { "type": "ColumnSeries", "settings": { "name": "Europe", "xAxis": "#axis-0", "yAxis": "#axis-1", "valueYField": "europe", "categoryXField": "year", "stacked": true }, "properties": { "data": "#data-0", "columns": { "properties": { "template": { "settings": { "tooltipText": "{name}, {categoryX}:{valueY}", "width": { "type": "Percent", "value": 100 }, "tooltipY": 0, "cornerRadiusTL": 0, "cornerRadiusTR": 0, "cornerRadiusBL": 0, "cornerRadiusBR": 0 } } } }, "bullets": [ { "type": "Bullet", "settings": { "locationY": 0.5, "sprite": { "type": "Label", "settings": { "text": "{valueY}", "fill": "@root.interfaceColors.get('alternativeText')", "centerY": { "type": "Percent", "value": 50 }, "centerX": { "type": "Percent", "value": 50 }, "populateText": true, "oversizedBehavior": "hide" } } } } ] } } }, { "series-1": { "type": "ColumnSeries", "settings": { "name": "North America", "xAxis": "#axis-0", "yAxis": "#axis-1", "valueYField": "namerica", "categoryXField": "year", "stacked": true }, "properties": { "data": "#data-0", "columns": { "properties": { "template": { "settings": { "tooltipText": "{name}, {categoryX}:{valueY}", "width": { "type": "Percent", "value": 100 }, "tooltipY": 0, "cornerRadiusTL": 0, "cornerRadiusTR": 0, "cornerRadiusBL": 0, "cornerRadiusBR": 0 } } } }, "bullets": [ { "type": "Bullet", "settings": { "locationY": 0.5, "sprite": { "type": "Label", "settings": { "text": "{valueY}", "fill": "@root.interfaceColors.get('alternativeText')", "centerY": { "type": "Percent", "value": 50 }, "centerX": { "type": "Percent", "value": 50 }, "populateText": true, "oversizedBehavior": "hide" } } } } ] } } }, { "series-2": { "type": "ColumnSeries", "settings": { "name": "Asia", "xAxis": "#axis-0", "yAxis": "#axis-1", "valueYField": "asia", "categoryXField": "year", "stacked": false }, "properties": { "data": "#data-0", "columns": { "properties": { "template": { "settings": { "tooltipText": "{name}, {categoryX}:{valueY}", "width": { "type": "Percent", "value": 100 }, "tooltipY": 0, "cornerRadiusTL": 0, "cornerRadiusTR": 0, "cornerRadiusBL": 0, "cornerRadiusBR": 0 } } } }, "bullets": [ { "type": "Bullet", "settings": { "locationY": 0.5, "sprite": { "type": "Label", "settings": { "text": "{valueY}", "fill": "@root.interfaceColors.get('alternativeText')", "centerY": { "type": "Percent", "value": 50 }, "centerX": { "type": "Percent", "value": 50 }, "populateText": true, "oversizedBehavior": "hide" } } } } ] } } } ]}adaptively-rounded-corners-on-mixed-stacksAnother version with mixed positive and negative values:
/** * --------------------------------------- * This demo was created using amCharts 5. * * For more information visit: * https://www.amcharts.com/ * * Documentation is available at: * https://www.amcharts.com/docs/v5/ * --------------------------------------- */
// Create root element// https://www.amcharts.com/docs/v5/getting-started/#Root_elementvar root = am5.Root.new("chartdiv");
// Set themes// https://www.amcharts.com/docs/v5/concepts/themes/root.setThemes([am5themes_Animated.new(root)]);
// Create chart// https://www.amcharts.com/docs/v5/charts/xy-chart/var chart = root.container.children.push( am5xy.XYChart.new(root, { panX: false, panY: false, wheelX: "panX", wheelY: "zoomX", layout: root.verticalLayout }));
// Add legend// https://www.amcharts.com/docs/v5/charts/xy-chart/legend-xy-series/var legend = chart.children.push( am5.Legend.new(root, { centerX: am5.p50, x: am5.p50 }));
var data = [ { year: "2021", europe: 5, namerica: 9, asia: 21 }, { year: "2022", europe: 6, namerica: -6, asia: 22 }, { year: "2023", europe: 8, namerica: -9, asia: -2 }, { year: "2024", europe: -8, namerica: -4, asia: -6 }];
// Create axes// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/var xAxis = chart.xAxes.push( am5xy.CategoryAxis.new(root, { categoryField: "year", renderer: am5xy.AxisRendererX.new(root, { cellStartLocation: 0.1, cellEndLocation: 0.9 }),
tooltip: am5.Tooltip.new(root, {}) }));
xAxis.data.setAll(data);
var yAxis = chart.yAxes.push( am5xy.ValueAxis.new(root, { calculateTotals: true, renderer: am5xy.AxisRendererY.new(root, {}) }));
// Add series// https://www.amcharts.com/docs/v5/charts/xy-chart/series/function makeSeries(name, fieldName, position) { var series = chart.series.push( am5xy.ColumnSeries.new(root, { name: name, xAxis: xAxis, yAxis: yAxis, valueYField: fieldName, categoryXField: "year", stacked: true }) );
series.columns.template.setAll({ tooltipText: "{name}, {categoryX}:{valueY}", width: am5.p100, tooltipY: 0, cornerRadiusTL: 0, cornerRadiusTR: 0, cornerRadiusBL: 0, cornerRadiusBR: 0 });
// Handle top corners series.columns.template.adapters.add("cornerRadiusTL", function (radius, target) { return isTop(target.dataItem) ? 10 : 0; }); series.columns.template.adapters.add("cornerRadiusTR", function (radius, target) { return isTop(target.dataItem) ? 10 : 0; }); series.columns.template.adapters.add("cornerRadiusBL", function (radius, target) { return isBottom(target.dataItem) ? 10 : 0; }); series.columns.template.adapters.add("cornerRadiusBR", function (radius, target) { return isBottom(target.dataItem) ? 10 : 0; });
function getCategoryDataItems(dataItem) { var targetSeries = dataItem.component; var index = xAxis.categoryToIndex(dataItem.get("categoryX")); var items = []; chart.series.each(function (series) { if (series.get("visible")) { var item = series.dataItems[index]; if (item.get("valueY") >= 0) { items.push(item); } else { items.unshift(item); } } }); return items; }
// Corner handling functions function isBottom(dataItem) { var items = getCategoryDataItems(dataItem); if (dataItem.get("valueY") >= 0) { return items.indexOf(dataItem) == 0; } else { return items.indexOf(dataItem) == items.length - 1; } }
function isTop(dataItem) { var items = getCategoryDataItems(dataItem); if (dataItem.get("valueY") >= 0) { return items.indexOf(dataItem) == items.length - 1; } else { return items.indexOf(dataItem) == 0; } }
series.bullets.push(function () { return am5.Bullet.new(root, { locationY: 0.5, sprite: am5.Label.new(root, { text: "{valueY}", fill: root.interfaceColors.get("alternativeText"), centerY: am5.p50, centerX: am5.p50, populateText: true, oversizedBehavior: "hide" }) }); });
series.data.setAll(data); series.appear(); legend.data.push(series);}
makeSeries("Europe", "europe");makeSeries("North America", "namerica");makeSeries("Asia", "asia");
// Make stuff animate on load// https://www.amcharts.com/docs/v5/concepts/animations/chart.appear(1000, 100);<div id="chartdiv"></div>body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";}
#chartdiv { width: 100%; height: 95vh;}{ "type": "XYChart", "settings": { "panX": false, "panY": false, "wheelX": "panX", "wheelY": "zoomX", "layout": { "type": "VerticalLayout" } }, "properties": { "series": [ "#series-0", "#series-1", "#series-2" ], "xAxes": [ "#axis-0" ], "yAxes": [ "#axis-1" ] }, "children": [ { "type": "Legend", "settings": { "centerX": { "type": "Percent", "value": 50 }, "x": { "type": "Percent", "value": 50 } }, "properties": { "data": [ "#series-0", "#series-1", "#series-2" ] } } ], "refs": [ { "data-0": [ { "year": "2021", "europe": 5, "namerica": 9, "asia": 21 }, { "year": "2022", "europe": 6, "namerica": -6, "asia": 22 }, { "year": "2023", "europe": 8, "namerica": -9, "asia": -2 }, { "year": "2024", "europe": -8, "namerica": -4, "asia": -6 } ] }, { "axis-0": { "type": "CategoryAxis", "settings": { "categoryField": "year", "renderer": { "type": "AxisRendererX", "settings": { "cellStartLocation": 0.1, "cellEndLocation": 0.9 } }, "tooltip": { "type": "Tooltip" } }, "properties": { "data": "#data-0" } } }, { "axis-1": { "type": "ValueAxis", "settings": { "calculateTotals": true, "renderer": { "type": "AxisRendererY" } } } }, { "series-0": { "type": "ColumnSeries", "settings": { "name": "Europe", "xAxis": "#axis-0", "yAxis": "#axis-1", "valueYField": "europe", "categoryXField": "year", "stacked": true }, "properties": { "data": "#data-0", "columns": { "properties": { "template": { "settings": { "tooltipText": "{name}, {categoryX}:{valueY}", "width": { "type": "Percent", "value": 100 }, "tooltipY": 0, "cornerRadiusTL": 0, "cornerRadiusTR": 0, "cornerRadiusBL": 0, "cornerRadiusBR": 0 } } } }, "bullets": [ { "type": "Bullet", "settings": { "locationY": 0.5, "sprite": { "type": "Label", "settings": { "text": "{valueY}", "fill": "@root.interfaceColors.get('alternativeText')", "centerY": { "type": "Percent", "value": 50 }, "centerX": { "type": "Percent", "value": 50 }, "populateText": true, "oversizedBehavior": "hide" } } } } ] } } }, { "series-1": { "type": "ColumnSeries", "settings": { "name": "North America", "xAxis": "#axis-0", "yAxis": "#axis-1", "valueYField": "namerica", "categoryXField": "year", "stacked": true }, "properties": { "data": "#data-0", "columns": { "properties": { "template": { "settings": { "tooltipText": "{name}, {categoryX}:{valueY}", "width": { "type": "Percent", "value": 100 }, "tooltipY": 0, "cornerRadiusTL": 0, "cornerRadiusTR": 0, "cornerRadiusBL": 0, "cornerRadiusBR": 0 } } } }, "bullets": [ { "type": "Bullet", "settings": { "locationY": 0.5, "sprite": { "type": "Label", "settings": { "text": "{valueY}", "fill": "@root.interfaceColors.get('alternativeText')", "centerY": { "type": "Percent", "value": 50 }, "centerX": { "type": "Percent", "value": 50 }, "populateText": true, "oversizedBehavior": "hide" } } } } ] } } }, { "series-2": { "type": "ColumnSeries", "settings": { "name": "Asia", "xAxis": "#axis-0", "yAxis": "#axis-1", "valueYField": "asia", "categoryXField": "year", "stacked": true }, "properties": { "data": "#data-0", "columns": { "properties": { "template": { "settings": { "tooltipText": "{name}, {categoryX}:{valueY}", "width": { "type": "Percent", "value": 100 }, "tooltipY": 0, "cornerRadiusTL": 0, "cornerRadiusTR": 0, "cornerRadiusBL": 0, "cornerRadiusBR": 0 } } } }, "bullets": [ { "type": "Bullet", "settings": { "locationY": 0.5, "sprite": { "type": "Label", "settings": { "text": "{valueY}", "fill": "@root.interfaceColors.get('alternativeText')", "centerY": { "type": "Percent", "value": 50 }, "centerX": { "type": "Percent", "value": 50 }, "populateText": true, "oversizedBehavior": "hide" } } } } ] } } } ]}adaptively-rounded-corners-width-positive-and-negative-value