Amcharts:具有多个系列的堆积柱
Amcharts: stacked columns with multiple series
我在一个图表中有多个系列,例如在这个代码笔中看到的:
let chart = am4core.create("chartdiv", am4charts.XYChart);
chart.leftAxesContainer.layout = "vertical";
chart.numberFormatter.numberFormat = '# €';
chart.data = [
{name: "2011\nLorient", transport: 56, stay: 200, costByNight: 29, costByKm: 14},
{name: "2015\nPoitiers\nLa Rochelle", transport: 96, stay: 54, costByNight: 9, costByKm: 23},
{name: "2016\nRoyaume-Uni", transport: 160, stay: 332, costByNight: 47, costByKm: 62},
{name: "2016\nBiarritz", transport: 185, stay: 516, costByNight: 74, costByKm: 27},
{name: "2017\nRoyaume-Uni", transport: 258, stay: 355, costByNight: 36, costByKm: 24},
{name: "2018\nSingapour\nVietnam\nTaïwan", transport: 1020, stay: 622, costByNight: 41, costByKm: 8},
{name: "2018\nVietnam", transport: 753, stay: 294, costByNight: 49, costByKm: 8},
{name: "2019\nCanada", transport: 1074, stay: 342, costByNight: 38, costByKm: 13},
{name: "2019\nLorient\nGroix", transport: 77, stay: 190, costByNight: 27, costByKm: 20}
];
chart.padding(20, 5, 2, 5);
// Cities/countries names
let categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.renderer.grid.template.location = 0;
categoryAxis.dataFields.category = "name";
categoryAxis.renderer.ticks.template.disabled = false;
categoryAxis.renderer.minGridDistance = 1;
categoryAxis.renderer.labels.template.wrap = true;
categoryAxis.renderer.labels.template.maxWidth = 100;
categoryAxis.renderer.labels.template.fontSize = ".75em";
categoryAxis.renderer.labels.template.textAlign = "middle";
/* FIRST CHART */
// First Y axis
let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.tooltip.disabled = true;
valueAxis.zIndex = 1;
valueAxis.renderer.baseGrid.disabled = true;
valueAxis.renderer.fontSize = "0.8em";
// Transport
let series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Transport";
series.dataFields.valueY = "transport";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis;
// Configure columns
series.columns.template.width = am4core.percent(100);
series.columns.template.tooltipText = "[font-size:13px]Transport : {valueY}";
series.columns.template.fillOpacity = .8;
// Logement
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Logement";
series.dataFields.valueY = "stay";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis;
// Make it stacked
series.stacked = true;
// Configure columns
series.columns.template.width = am4core.percent(100);
series.columns.template.tooltipText = "[font-size:13px]Logement : {valueY}";
series.columns.template.fillOpacity = .8;
/* SECOND CHART */
let valueAxis2 = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis2.marginTop = 50;
valueAxis2.tooltip.disabled = true;
valueAxis2.renderer.baseGrid.disabled = true;
valueAxis2.zIndex = 3;
valueAxis2.renderer.fontSize = "0.8em";
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Prix par 200km";
series.dataFields.valueY = "costByKm";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis2;
series.stacked = true;
// Configure columns
series.columns.template.width = am4core.percent(40);
series.columns.template.tooltipText = "[font-size:13px]Prix pour 200km : {valueY}";
series.columns.template.fillOpacity = .8;
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Prix par nuitée";
series.dataFields.valueY = "costByNight";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis2;
// Configure columns
series.columns.template.width = am4core.percent(40);
series.columns.template.tooltipText = "[font-size:13px]Prix par nuit : {valueY}";
series.columns.template.fillOpacity = .8;
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: 350px;
}
<script src="//www.amcharts.com/lib/4/core.js"></script>
<script src="//www.amcharts.com/lib/4/charts.js"></script>
<script src="//www.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>
我想做但不知道怎么做的是:
- 使顶部列获得两个相应底部列的宽度(如某种 colspan)
- 使底部系列相反,具有某种对称性(我尝试过相反= true,但它让一切都破裂了)
- 两个图表之间有共同的 x 轴
预期的结果是这样的:
Expected result
你能帮助实现至少其中一个目标吗?谢谢!
您可以使用您正在使用的堆叠值轴方法从三个中获得两个。
列系列将始终为其他列保留 space,无论是否存在值,因此您无法强制顶部图表的列完全展开。一个解决方法是创建第二个不可见的类别轴(禁用标签和网格)并将底部系列'xAxis
分配给第二个类别轴:
let categoryAxis2 = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis2.renderer.grid.template.location = 0;
categoryAxis2.dataFields.category = "name";
categoryAxis2.renderer.ticks.template.disabled = true;
categoryAxis2.renderer.minGridDistance = 1;
categoryAxis2.renderer.labels.template.disabled = true;
// ...
series.xAxis = categoryAxis2; //repeat for both bottom chart's series
// ...
这将使顶部图表的列扩展到全宽,因为其他列完全与不同的轴相关联。
要反转底部图表以从顶部停止,请在值轴的渲染器对象中将 inversed
设置为 true:
valueAxis2.renderer.inversed = true;
但是分类轴不能放在中间。
下面的演示:
let chart = am4core.create("chartdiv", am4charts.XYChart);
chart.leftAxesContainer.layout = "vertical";
chart.numberFormatter.numberFormat = '# €';
chart.data = [
{name: "2011\nLorient", transport: 56, stay: 200, costByNight: 29, costByKm: 14},
{name: "2015\nPoitiers\nLa Rochelle", transport: 96, stay: 54, costByNight: 9, costByKm: 23},
{name: "2016\nRoyaume-Uni", transport: 160, stay: 332, costByNight: 47, costByKm: 62},
{name: "2016\nBiarritz", transport: 185, stay: 516, costByNight: 74, costByKm: 27},
{name: "2017\nRoyaume-Uni", transport: 258, stay: 355, costByNight: 36, costByKm: 24},
{name: "2018\nSingapour\nVietnam\nTaïwan", transport: 1020, stay: 622, costByNight: 41, costByKm: 8},
{name: "2018\nVietnam", transport: 753, stay: 294, costByNight: 49, costByKm: 8},
{name: "2019\nCanada", transport: 1074, stay: 342, costByNight: 38, costByKm: 13},
{name: "2019\nLorient\nGroix", transport: 77, stay: 190, costByNight: 27, costByKm: 20}
];
chart.padding(20, 5, 2, 5);
// Cities/countries names
let categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.renderer.grid.template.location = 0;
categoryAxis.dataFields.category = "name";
categoryAxis.renderer.ticks.template.disabled = false;
categoryAxis.renderer.minGridDistance = 1;
categoryAxis.renderer.labels.template.wrap = true;
categoryAxis.renderer.labels.template.maxWidth = 100;
categoryAxis.renderer.labels.template.fontSize = ".75em";
categoryAxis.renderer.labels.template.textAlign = "middle";
/* FIRST CHART */
// First Y axis
let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.tooltip.disabled = true;
valueAxis.zIndex = 1;
valueAxis.renderer.baseGrid.disabled = true;
valueAxis.renderer.fontSize = "0.8em";
// Transport
let series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Transport";
series.dataFields.valueY = "transport";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis;
// Configure columns
series.columns.template.width = am4core.percent(100);
series.columns.template.tooltipText = "[font-size:13px]Transport : {valueY}";
series.columns.template.fillOpacity = .8;
// Logement
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Logement";
series.dataFields.valueY = "stay";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis;
// Make it stacked
series.stacked = true;
// Configure columns
series.columns.template.width = am4core.percent(100);
series.columns.template.tooltipText = "[font-size:13px]Logement : {valueY}";
series.columns.template.fillOpacity = .8;
/* SECOND CHART */
let valueAxis2 = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis2.marginTop = 50;
valueAxis2.renderer.inversed = true;
valueAxis2.tooltip.disabled = true;
valueAxis2.renderer.baseGrid.disabled = true;
valueAxis2.zIndex = 3;
valueAxis2.renderer.fontSize = "0.8em";
let categoryAxis2 = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis2.renderer.grid.template.location = 0;
categoryAxis2.dataFields.category = "name";
categoryAxis2.renderer.ticks.template.disabled = true;
categoryAxis2.renderer.minGridDistance = 1;
categoryAxis2.renderer.labels.template.disabled = true;
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Prix par 200km";
series.dataFields.valueY = "costByKm";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis2;
series.stacked = true;
// Configure columns
series.columns.template.width = am4core.percent(40);
series.columns.template.tooltipText = "[font-size:13px]Prix pour 200km : {valueY}";
series.columns.template.fillOpacity = .8;
series.xAxis = categoryAxis2;
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Prix par nuitée";
series.dataFields.valueY = "costByNight";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis2;
series.xAxis = categoryAxis2;
// Configure columns
series.columns.template.width = am4core.percent(40);
series.columns.template.tooltipText = "[font-size:13px]Prix par nuit : {valueY}";
series.columns.template.fillOpacity = .8;
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: 350px;
}
<script src="//www.amcharts.com/lib/4/core.js"></script>
<script src="//www.amcharts.com/lib/4/charts.js"></script>
<script src="//www.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>
我在一个图表中有多个系列,例如在这个代码笔中看到的:
let chart = am4core.create("chartdiv", am4charts.XYChart);
chart.leftAxesContainer.layout = "vertical";
chart.numberFormatter.numberFormat = '# €';
chart.data = [
{name: "2011\nLorient", transport: 56, stay: 200, costByNight: 29, costByKm: 14},
{name: "2015\nPoitiers\nLa Rochelle", transport: 96, stay: 54, costByNight: 9, costByKm: 23},
{name: "2016\nRoyaume-Uni", transport: 160, stay: 332, costByNight: 47, costByKm: 62},
{name: "2016\nBiarritz", transport: 185, stay: 516, costByNight: 74, costByKm: 27},
{name: "2017\nRoyaume-Uni", transport: 258, stay: 355, costByNight: 36, costByKm: 24},
{name: "2018\nSingapour\nVietnam\nTaïwan", transport: 1020, stay: 622, costByNight: 41, costByKm: 8},
{name: "2018\nVietnam", transport: 753, stay: 294, costByNight: 49, costByKm: 8},
{name: "2019\nCanada", transport: 1074, stay: 342, costByNight: 38, costByKm: 13},
{name: "2019\nLorient\nGroix", transport: 77, stay: 190, costByNight: 27, costByKm: 20}
];
chart.padding(20, 5, 2, 5);
// Cities/countries names
let categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.renderer.grid.template.location = 0;
categoryAxis.dataFields.category = "name";
categoryAxis.renderer.ticks.template.disabled = false;
categoryAxis.renderer.minGridDistance = 1;
categoryAxis.renderer.labels.template.wrap = true;
categoryAxis.renderer.labels.template.maxWidth = 100;
categoryAxis.renderer.labels.template.fontSize = ".75em";
categoryAxis.renderer.labels.template.textAlign = "middle";
/* FIRST CHART */
// First Y axis
let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.tooltip.disabled = true;
valueAxis.zIndex = 1;
valueAxis.renderer.baseGrid.disabled = true;
valueAxis.renderer.fontSize = "0.8em";
// Transport
let series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Transport";
series.dataFields.valueY = "transport";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis;
// Configure columns
series.columns.template.width = am4core.percent(100);
series.columns.template.tooltipText = "[font-size:13px]Transport : {valueY}";
series.columns.template.fillOpacity = .8;
// Logement
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Logement";
series.dataFields.valueY = "stay";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis;
// Make it stacked
series.stacked = true;
// Configure columns
series.columns.template.width = am4core.percent(100);
series.columns.template.tooltipText = "[font-size:13px]Logement : {valueY}";
series.columns.template.fillOpacity = .8;
/* SECOND CHART */
let valueAxis2 = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis2.marginTop = 50;
valueAxis2.tooltip.disabled = true;
valueAxis2.renderer.baseGrid.disabled = true;
valueAxis2.zIndex = 3;
valueAxis2.renderer.fontSize = "0.8em";
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Prix par 200km";
series.dataFields.valueY = "costByKm";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis2;
series.stacked = true;
// Configure columns
series.columns.template.width = am4core.percent(40);
series.columns.template.tooltipText = "[font-size:13px]Prix pour 200km : {valueY}";
series.columns.template.fillOpacity = .8;
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Prix par nuitée";
series.dataFields.valueY = "costByNight";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis2;
// Configure columns
series.columns.template.width = am4core.percent(40);
series.columns.template.tooltipText = "[font-size:13px]Prix par nuit : {valueY}";
series.columns.template.fillOpacity = .8;
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: 350px;
}
<script src="//www.amcharts.com/lib/4/core.js"></script>
<script src="//www.amcharts.com/lib/4/charts.js"></script>
<script src="//www.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>
我想做但不知道怎么做的是: - 使顶部列获得两个相应底部列的宽度(如某种 colspan) - 使底部系列相反,具有某种对称性(我尝试过相反= true,但它让一切都破裂了) - 两个图表之间有共同的 x 轴
预期的结果是这样的: Expected result
你能帮助实现至少其中一个目标吗?谢谢!
您可以使用您正在使用的堆叠值轴方法从三个中获得两个。
列系列将始终为其他列保留 space,无论是否存在值,因此您无法强制顶部图表的列完全展开。一个解决方法是创建第二个不可见的类别轴(禁用标签和网格)并将底部系列'xAxis
分配给第二个类别轴:
let categoryAxis2 = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis2.renderer.grid.template.location = 0;
categoryAxis2.dataFields.category = "name";
categoryAxis2.renderer.ticks.template.disabled = true;
categoryAxis2.renderer.minGridDistance = 1;
categoryAxis2.renderer.labels.template.disabled = true;
// ...
series.xAxis = categoryAxis2; //repeat for both bottom chart's series
// ...
这将使顶部图表的列扩展到全宽,因为其他列完全与不同的轴相关联。
要反转底部图表以从顶部停止,请在值轴的渲染器对象中将 inversed
设置为 true:
valueAxis2.renderer.inversed = true;
但是分类轴不能放在中间。
下面的演示:
let chart = am4core.create("chartdiv", am4charts.XYChart);
chart.leftAxesContainer.layout = "vertical";
chart.numberFormatter.numberFormat = '# €';
chart.data = [
{name: "2011\nLorient", transport: 56, stay: 200, costByNight: 29, costByKm: 14},
{name: "2015\nPoitiers\nLa Rochelle", transport: 96, stay: 54, costByNight: 9, costByKm: 23},
{name: "2016\nRoyaume-Uni", transport: 160, stay: 332, costByNight: 47, costByKm: 62},
{name: "2016\nBiarritz", transport: 185, stay: 516, costByNight: 74, costByKm: 27},
{name: "2017\nRoyaume-Uni", transport: 258, stay: 355, costByNight: 36, costByKm: 24},
{name: "2018\nSingapour\nVietnam\nTaïwan", transport: 1020, stay: 622, costByNight: 41, costByKm: 8},
{name: "2018\nVietnam", transport: 753, stay: 294, costByNight: 49, costByKm: 8},
{name: "2019\nCanada", transport: 1074, stay: 342, costByNight: 38, costByKm: 13},
{name: "2019\nLorient\nGroix", transport: 77, stay: 190, costByNight: 27, costByKm: 20}
];
chart.padding(20, 5, 2, 5);
// Cities/countries names
let categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.renderer.grid.template.location = 0;
categoryAxis.dataFields.category = "name";
categoryAxis.renderer.ticks.template.disabled = false;
categoryAxis.renderer.minGridDistance = 1;
categoryAxis.renderer.labels.template.wrap = true;
categoryAxis.renderer.labels.template.maxWidth = 100;
categoryAxis.renderer.labels.template.fontSize = ".75em";
categoryAxis.renderer.labels.template.textAlign = "middle";
/* FIRST CHART */
// First Y axis
let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.tooltip.disabled = true;
valueAxis.zIndex = 1;
valueAxis.renderer.baseGrid.disabled = true;
valueAxis.renderer.fontSize = "0.8em";
// Transport
let series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Transport";
series.dataFields.valueY = "transport";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis;
// Configure columns
series.columns.template.width = am4core.percent(100);
series.columns.template.tooltipText = "[font-size:13px]Transport : {valueY}";
series.columns.template.fillOpacity = .8;
// Logement
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Logement";
series.dataFields.valueY = "stay";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis;
// Make it stacked
series.stacked = true;
// Configure columns
series.columns.template.width = am4core.percent(100);
series.columns.template.tooltipText = "[font-size:13px]Logement : {valueY}";
series.columns.template.fillOpacity = .8;
/* SECOND CHART */
let valueAxis2 = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis2.marginTop = 50;
valueAxis2.renderer.inversed = true;
valueAxis2.tooltip.disabled = true;
valueAxis2.renderer.baseGrid.disabled = true;
valueAxis2.zIndex = 3;
valueAxis2.renderer.fontSize = "0.8em";
let categoryAxis2 = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis2.renderer.grid.template.location = 0;
categoryAxis2.dataFields.category = "name";
categoryAxis2.renderer.ticks.template.disabled = true;
categoryAxis2.renderer.minGridDistance = 1;
categoryAxis2.renderer.labels.template.disabled = true;
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Prix par 200km";
series.dataFields.valueY = "costByKm";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis2;
series.stacked = true;
// Configure columns
series.columns.template.width = am4core.percent(40);
series.columns.template.tooltipText = "[font-size:13px]Prix pour 200km : {valueY}";
series.columns.template.fillOpacity = .8;
series.xAxis = categoryAxis2;
series = chart.series.push(new am4charts.ColumnSeries());
series.name = "Prix par nuitée";
series.dataFields.valueY = "costByNight";
series.dataFields.categoryX = "name";
series.yAxis = valueAxis2;
series.xAxis = categoryAxis2;
// Configure columns
series.columns.template.width = am4core.percent(40);
series.columns.template.tooltipText = "[font-size:13px]Prix par nuit : {valueY}";
series.columns.template.fillOpacity = .8;
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: 350px;
}
<script src="//www.amcharts.com/lib/4/core.js"></script>
<script src="//www.amcharts.com/lib/4/charts.js"></script>
<script src="//www.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>