You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 04:42:02