如何让ECharts跟随react-grid-layout的网格项同步调整尺寸?
React-Grid-Layout嵌入ECharts调整尺寸不同步解决方案
问题根因
ECharts默认不会自动监听父容器的尺寸变化,React-Grid-Layout调整网格项尺寸时仅修改了容器的宽高属性,没有触发ECharts实例的重绘逻辑,因此出现图表尺寸不同步的问题。你之前配置的onLayoutChange不生效是因为该事件仅在尺寸调整结束后才触发,无法实现调整过程中的实时同步,且如果没有在回调中正确调用ECharts的resize方法也会不生效。
可行解决方案
推荐使用ResizeObserver监听网格项容器的尺寸变化,自动触发ECharts重绘,不需要依赖React-Grid-Layout的事件回调,适配性更强,具体实现步骤如下:
- 第一步:分别声明ref存储ECharts实例和网格项的DOM节点,同时设置ECharts容器宽高为100%,继承父容器尺寸
import { useRef, useEffect } from 'react'; import * as echarts from 'echarts'; import { Responsive, WidthProvider } from 'react-grid-layout'; const ResponsiveGridLayout = WidthProvider(Responsive); const ChartItem = () => { // 存储ECharts实例 const chartInstanceRef = useRef(null); // 存储网格项容器DOM const gridItemDomRef = useRef(null); // 初始化ECharts useEffect(() => { if (!gridItemDomRef.current) return; const chartInstance = echarts.init(gridItemDomRef.current); chartInstance.setOption({ // 你的ECharts配置项 xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: { type: 'value' }, series: [{ data: [150, 230, 224, 218, 135, 147, 260], type: 'line' }] }); chartInstanceRef.current = chartInstance; // 组件卸载销毁实例 return () => chartInstance.dispose(); }, []); // 监听容器尺寸变化触发resize useEffect(() => { if (!chartInstanceRef.current || !gridItemDomRef.current) return; const resizeObserver = new ResizeObserver(() => { chartInstanceRef.current.resize(); }); resizeObserver.observe(gridItemDomRef.current); // 清理监听 return () => resizeObserver.disconnect(); }, []); return <div ref={gridItemDomRef} style={{ width: '100%', height: '100%' }} /> }
- 第二步:正常使用ResponsiveGridLayout组件即可,不需要额外配置事件回调,每个图表组件会自动监听自身容器尺寸变化同步更新
const App = () => { const layout = [ { i: 'chart1', x: 0, y: 0, w: 6, h: 4 }, { i: 'chart2', x: 6, y: 0, w: 6, h: 4 } ]; return ( <ResponsiveGridLayout className="layout" layouts={{ lg: layout }} breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }} cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }} isResizable={true} isDraggable={true} > <div key="chart1"><ChartItem /></div> <div key="chart2"><ChartItem /></div> </ResponsiveGridLayout> ) }
注意事项
- 不要给ECharts的DOM节点设置固定宽高,必须设置宽高为100%继承父网格项的尺寸,否则容器宽高变化时图表DOM本身尺寸不会变
- 如果不想用ResizeObserver,也可以改用ResponsiveGridLayout的
onResize事件,该事件会在调整尺寸的过程中实时触发,在回调中找到对应图表实例调用resize()方法即可,体验和ResizeObserver一致
内容的提问来源于stack exchange,提问作者yongchang
相关产品推荐
相关产品推荐

