基于CanvasJS实现页面多图表的缩放与平移同步
解决CanvasJS React多图表同步缩放平移问题
核心问题分析
你的代码主要存在两个导致同步失效的问题:
- 子Chart组件未监听父组件传递的范围状态变化,无法触发图表更新
- 图表的
zoom和pan事件未正确绑定到同步逻辑,且未处理循环触发的问题
具体修改方案
1. 父组件(App.js)调整
- 维护统一的
xRange状态存储当前X轴范围 - 实现范围更新函数,接收新范围并同步状态
- 给每个Chart组件传递
xRange和更新回调
修改后的核心代码:
import { useState } from 'react'; import Chart from './Chart'; function App() { const [xRange, setXRange] = useState(null); const handleRangeChange = (newRange) => { setXRange(newRange); }; return ( <div className="App"> <Chart title="图表1" xRange={xRange} onRangeChange={handleRangeChange} /> <Chart title="图表2" xRange={xRange} onRangeChange={handleRangeChange} /> </div> ); } export default App;
2. 子组件(Chart.js)修改
- 用
useEffect监听xRange变化,触发CanvasJS的zoomTo方法同步范围 - 初始化图表时绑定
zoom和pan事件,调用父组件回调时添加标记避免循环触发 - 保存图表实例到ref,方便后续操作
修改后的核心代码:
import { useEffect, useRef, useState } from 'react'; import CanvasJSReact from '@canvasjs/react-charts'; const CanvasJSChart = CanvasJSReact.CanvasJSChart; function Chart({ title, xRange, onRangeChange }) { const chartRef = useRef(null); const isUpdating = useRef(false); // 标记同步状态,避免循环触发 const options = { title: { text: title }, axisX: { title: "时间", zoomEnabled: true, panEnabled: true }, axisY: { title: "数值" }, data: [{ type: "line", dataPoints: Array.from({ length: 50 }, (_, i) => ({ x: new Date(2024, 0, i+1), y: Math.random() * 100 })) }] }; // 监听范围变化,同步图表视图 useEffect(() => { if (xRange && chartRef.current && !isUpdating.current) { isUpdating.current = true; chartRef.current.zoomTo("x", xRange.min, xRange.max); isUpdating.current = false; } }, [xRange]); // 绑定缩放/平移事件 useEffect(() => { const chart = chartRef.current; if (!chart) return; const handleSync = () => { if (isUpdating.current) return; const axisX = chart.axisX[0]; onRangeChange({ min: axisX.viewportMinimum, max: axisX.viewportMaximum }); }; chart.addEventListener("zoom", handleSync); chart.addEventListener("pan", handleSync); return () => { chart.removeEventListener("zoom", handleSync); chart.removeEventListener("pan", handleSync); }; }, [onRangeChange]); return ( <div> <CanvasJSChart options={options} onRef={ref => chartRef.current = ref} /> </div> ); } export default Chart;
关键说明
isUpdatingref用于避免同步更新时再次触发事件回调,防止无限循环- 通过
onRef获取CanvasJS图表实例,才能调用zoomTo方法和绑定事件 - 父组件统一维护X轴范围,所有子组件监听该状态实现同步
内容的提问来源于stack exchange,提问作者shifoc
相关产品推荐
相关产品推荐

