AmCharts4折线图可垂直拖拽锚点X轴缩放后不跟随问题
问题根因
为了限制锚点仅支持垂直拖拽,原代码在锚点的positionchanged事件中固定了每个锚点的minX和maxX值。当你通过滚动条缩放X轴时,日期轴会重新计算所有数据点的X轴像素坐标,但之前已经固定的锚点X范围没有同步更新,就会出现锚点和折线位置错位的问题。
修复后的完整实现代码
JS代码
am4core.useTheme(am4themes_animated); // 创建图表实例 var chart = am4core.create("chartdiv", am4charts.XYChart); // 添加数据 chart.data = [ { date: new Date(2018, 0, 1), value: 450 }, { date: new Date(2018, 0, 2), value: 269 }, { date: new Date(2018, 0, 3), value: 700 }, { date: new Date(2018, 0, 4), value: 490 }, { date: new Date(2018, 0, 5), value: 500 }, { date: new Date(2018, 0, 6), value: 550 }, { date: new Date(2018, 0, 7), value: 420 } ]; // 创建坐标轴 var dateAxis = chart.xAxes.push(new am4charts.DateAxis()); dateAxis.renderer.grid.template.location = 0; dateAxis.renderer.minGridDistance = 40; var valueAxis = chart.yAxes.push(new am4charts.ValueAxis()); // 统一更新所有锚点的X轴限制 function updateAllBulletsXRange() { chart.series.each(function(series) { series.bullets.each(function(bullet) { series.dataItems.each(function(dataItem) { if (dataItem.bullets && dataItem.point) { let itemBullet = dataItem.bullets.getKey(bullet.uid); if (itemBullet) { itemBullet.minX = dataItem.point.x; itemBullet.maxX = dataItem.point.x; itemBullet.minY = 0; itemBullet.maxY = chart.seriesContainer.pixelHeight; } } }) }) }) } // 监听X轴范围变化,更新锚点位置 dateAxis.events.on("rangechanged", updateAllBulletsXRange); // 图表重绘完成后也更新一次锚点位置 chart.events.on("ready", updateAllBulletsXRange); chart.events.on("datavalidated", updateAllBulletsXRange); // 创建序列 function createSeries(field, name) { var series = chart.series.push(new am4charts.LineSeries()); series.dataFields.valueY = field; series.dataFields.dateX = "date"; series.name = name; series.tooltipText = "{dateX}: [b]{valueY}[/]"; series.strokeWidth = 2; var bullet = series.bullets.push(new am4charts.CircleBullet()); bullet.circle.stroke = am4core.color("#fff"); bullet.circle.strokeWidth = 2; bullet.draggable = true; // 鼠标悬停时显示垂直调整光标 bullet.cursorOverStyle = am4core.MouseCursorStyle.verticalResize; // 拖拽中事件 bullet.events.on("drag", (event) => { handleDrag(event); }); // 拖拽结束事件 bullet.events.on("dragstop", (event) => { handleDragStop(event); }); // 锚点位置变化时更新自身X范围 bullet.events.on("positionchanged", (event) => { let dataItem = event.target.dataItem; if (dataItem.bullets && dataItem.point) { let itemBullet = dataItem.bullets.getKey(bullet.uid); itemBullet.minX = dataItem.point.x; itemBullet.maxX = itemBullet.minX; itemBullet.minY = 0; itemBullet.maxY = chart.seriesContainer.pixelHeight; } }); } createSeries("value", "Series #1"); chart.cursor = new am4charts.XYCursor(); chart.scrollbarX = new am4core.Scrollbar(); /* 拖拽事件处理函数 */ function handleDrag(event) { let dataItem = event.target.dataItem; // 将坐标转换为数值 let value = valueAxis.yToValue(event.target.pixelY); // 设置新数值 dataItem.valueY = value; // 触发展折线 hover 状态 dataItem.segment.isHover = true; // 隐藏提示框避免干扰 dataItem.segment.hideTooltip(0); // 触发锚点 hover 状态,避免鼠标移开后锚点隐藏 event.target.isHover = true; } /* 拖拽结束事件处理函数 */ function handleDragStop(event) { handleDrag(event); let dataItem = event.target.dataItem; dataItem.component.isHover = false; event.target.isHover = false; }
CSS代码(无修改)
#chartdiv { width: 100%; height: 500px; }
HTML代码(无修改)
<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>
内容的提问来源于stack exchange,提问作者Stéphane Laurent
相关产品推荐
相关产品推荐

