Amcharts 5 柱状图排序后部分柱状条消失问题求助
问题:Amcharts 5排序Y轴后部分柱状条消失
- 用Amcharts 5做XY柱状图,Y轴是名称分类轴,X轴是0-1区间的比率值
- 页面加载时图表显示正常,但通过下拉菜单按
Exp_rank排序后,Y轴能正常排序,可部分柱状条(比如示例里的Mike)会消失 - 数据量少于7个时问题就没了,数据越多问题越严重
数据项格式示例:
{'name': 'John Doe', 'Rate': .2, 'Exp_rank': 0}
原因分析
你当前的排序逻辑直接操作series.dataItems和yAxis.dataItems的索引,有两个核心问题:
- 索引不匹配:手动设置
dataItem.set("index", n_idx)时,Exp_rank的值可能超出Y轴数据项的实际索引范围,或者和Amcharts内部维护的索引机制冲突,导致部分数据项没法正确关联到柱状条 - 数据同步错误:单独排序
series.dataItems却没同步更新Y轴的数据源,Amcharts 5的XY系列依赖轴和系列数据的双向绑定,手动改索引会直接破坏这种绑定关系,导致柱状条丢失
修复方案
正确的做法是重新排序原始数据源,再更新Y轴和系列的数据,保证轴和系列的数据同步,避免绑定关系断裂:
- 排序时根据指定字段对原始数据做排序
- 调用
yAxis.data.setAll()更新Y轴数据 - 调用
series.data.setAll()更新系列数据 - 要保留动画的话,用轴的
animateDataItems方法实现平滑过渡
完整修复代码
<!-- Resources --> <script src='https://cdn.amcharts.com/lib/5/index.js'></script> <script src='https://cdn.amcharts.com/lib/5/xy.js'></script> <script src='https://cdn.amcharts.com/lib/5/themes/Animated.js'></script> <script src='https://cdn.amcharts.com/lib/5/stock.js'></script> <div id="chartdiv" style="width: 100%; height: 600px;"></div> <div id="chartcontrols"></div> <script> var barchart; sortdict = {'id1': 'Exp_rank'}; var root = am5.Root.new("chartdiv"); root.setThemes([ am5themes_Animated.new(root) ]); var chart = root.container.children.push( am5.Container.new(root, { layout: root.gridLayout, width: am5.percent(70), height: am5.percent(100), }) ) chartstuff = create_bar('Rate','Test Chart'); // 保存原始数据,用于排序 let originalData = [ { name: 'John', Rate: 0.005, Exp_rank: 0 }, { name: 'Steve', Rate: 0.005, Exp_rank: 1 }, { name: 'Josh', Rate: 0.005, Exp_rank: 6 }, { name: 'Greg', Rate: 0.005, Exp_rank: 7 }, { name: 'Brandon', Rate: 0.0556, Exp_rank: 2 }, { name: 'Dirk', Rate: 0.0833, Exp_rank: 3 }, { name: 'Sean', Rate: 0.0857, Exp_rank: 4 }, { name: 'Mike', Rate: 0.0909, Exp_rank: 5 } ] // parameters: html_title, category, values function create_bar(seriesName,title){ var barchart = chart.children.push( am5xy.XYChart.new( root, {width: am5.percent(50), height: am5.percent(85), paddingLeft: 100, marginTop: 100, }) ) barchart.children.unshift(am5.Label.new(root, { html: title, dy: -50, fontWeight: 'bold', fontSize: 17 } )) var xAxis = barchart.xAxes.push( am5xy.ValueAxis.new(root, { renderer: am5xy.AxisRendererX.new(root, { opacity: 1, numberFormat: "#.00'%'" }) }) ); var yAxis = barchart.yAxes.push( am5xy.CategoryAxis.new(root, { renderer: am5xy.AxisRendererY.new(root, { minGridDistance: 12 }), categoryField: 'name', }) ); const yAxisRenderer = yAxis.get('renderer'); const xAxisRenderer = xAxis.get('renderer'); yAxisRenderer.grid.template.setAll({ disabled: true, visible: false }); xAxisRenderer.grid.template.setAll({ disabled: true, visible: false }); yAxis.data.setAll(originalData); var series = barchart.series.push(am5xy.ColumnSeries.new(root, { name: seriesName, xAxis: xAxis, yAxis: yAxis, valueXField: 'Rate', categoryYField: 'name', fill: am5.color('#e1e1e1'), numberFormat : "#.00'%'", width: am5.percent(100), duration: 1000 }) ); series.columns.template.set("interactive", true); series.columns.template.set("tooltipText",'Rate: {valueX}'); xAxis.get('renderer').labels.template.set("fontSize", 12); yAxis.get('renderer').labels.template.set("fontSize", 10); series.data.setAll(originalData); series.appear(); let mysorter = am5stock.DropdownListControl.new(root, { stockChart: barchart, name: "Sorting options", items: [{ id: "id1", label: "Experience" }] }) var toolbar = am5stock.StockToolbar.new(root, { container: document.getElementById("chartcontrols"), stockChart: barchart, controls: [ mysorter ] }); mysorter.events.on("selected",function(ev){ sortCategoryAxis(series, ev.item.id, yAxis); }) return [series, barchart]; } function sortCategoryAxis(series,sortType, yAxis) { // 获取排序字段 const sortField = sortdict[sortType]; // 对原始数据排序 const sortedData = [...originalData].sort((a, b) => { return a[sortField] - b[sortField]; }); // 更新Y轴和系列数据,自动同步排序 yAxis.data.setAll(sortedData); series.data.setAll(sortedData); // 可选:添加轴数据项的动画过渡 yAxis.animateDataItems({ duration: 1000, easing: am5.ease.out(am5.ease.cubic) }); } </script>
关键修改点
- 把原始数据抽成全局变量
originalData,方便排序时复用 - 排序函数不再手动改数据项索引,直接对原始数据排序后更新轴和系列的数据源
- 用
yAxis.animateDataItems实现平滑排序动画,替代手动设置deltaPosition的复杂逻辑 - 删掉了没必要的
series.dataItems.sort操作,避免破坏内部数据结构
内容的提问来源于stack exchange,提问作者boody
相关产品推荐
相关产品推荐

