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

如何在React中实现Chart.js图表自适应并保持3.5:1固定宽高比

问题

开发React项目时,需要在网格布局的父组件中展示Chart.js图表,要求:

  • 图表随父容器尺寸自适应调整
  • 保持3.5:1(宽:高)的固定宽高比
  • 无需硬编码尺寸

当前代码结构如下:

父组件代码

<div className="graph_container">
  <h4>{title}</h4>
  <div className="graph_container_graph">
    <DynamicLineChart data={data} key={JSON.stringify(data)} />
  </div>
</div>

父组件样式

.graph_container {
  width: 100%;
  max-width: fit-content;
  border-radius: 1.27rem;
  background-color: #fff;
  padding: 0.95rem;
  display: flex;
  flex-direction: column;
  gap: 0.63rem;
  font-size: 1.4rem;
}

.graph_container_graph {
  padding: 0 0.95rem;
}

DynamicLineChart组件代码

import React, { useEffect } from 'react';
import { Line } from 'react-chartjs-2';
import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend } from 'chart.js';

ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend);

const DynamicLineChart = ({ data }) => {
  const chartData = {
    labels: Object.keys(data),
    datasets: [
      {
        data: Object.values(data),
        fill: false,
        backgroundColor: '#FFF',
        borderColor: '#6497FC',
        borderWidth: 3,
        pointBackgroundColor: '#4D5C92',
        pointBorderColor: '#4D5C92',
        pointRadius: 5,
        pointHoverRadius: 5,
      },
    ],
  };

  const options = {
    aspectRatio: 3.5,
    maintainAspectRatio: true,
    layout: {
      padding: {},
    },
    plugins: {
      legend: {
        display: false,
      },
      tooltip: {
        enabled: true,
      },
    },
    scales: {
      x: {
        grid: {
          borderDash: [15, 5],
          color: '#CDD1DB',
          borderColor: '#CDD1DB',
        },
        ticks: {
          color: '#6B7280',
          font: {
            size: 10,
          },
        },
      },
      y: {
        min: 0,
        max: 100,
        ticks: {
          font: {
            size: 10,
          },
          stepSize: 25,
          color: '#6B7280',
        },
        grid: {
          display: false,
        },
      },
    },
  };

  return (
    <div style={{ width: '100%', height: 'auto' }}>
      <Line data={chartData} options={options} />
    </div>
  );
};

export default DynamicLineChart;

目前遇到的问题:除非硬编码宽高,否则图表无法自适应。尝试过以下方法但无效:

  • 在图表配置中设置maintainAspectRatio: true
  • 用百分比宽度的div包裹Line组件
  • 通过CSS控制父容器尺寸

解决建议

1. 修复父容器宽度约束

父组件中.graph_container的max-width: fit-content会限制容器宽度为内容宽度,导致图表无法自适应网格布局。修改样式:

.graph_container {
  width: 100%;
  /* 移除fit-content限制,或改为100%/固定像素值 */
  /* max-width: fit-content; */
  border-radius: 1.27rem;
  background-color: #fff;
  padding: 0.95rem;
  display: flex;
  flex-direction: column;
  gap: 0.63rem;
  font-size: 1.4rem;
}

2. 用CSS padding-top实现固定宽高比

修改.graph_container_graph样式,通过padding-top模拟3.5:1的宽高比:

.graph_container_graph {
  padding: 0 0.95rem;
  width: 100%;
  position: relative;
  height: 0;
  /* 3.5:1对应高度=宽度/3.5,即padding-top=100%/3.5≈28.57% */
  padding-top: 28.57%; 
}

同时调整DynamicLineChart的外层容器,让图表填充整个占位容器:

return (
  <div style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }}>
    <Line data={chartData} options={options} />
  </div>
);

3. 添加窗口 resize 监听确保响应式

在DynamicLineChart组件中添加 useEffect,保证窗口尺寸变化时图表重绘:

useEffect(() => {
  const handleResize = () => {
    window.dispatchEvent(new Event('resize'));
  };

  window.addEventListener('resize', handleResize);
  return () => window.removeEventListener('resize', handleResize);
}, [data]);

4. 优化组件key属性(可选)

父组件中key={JSON.stringify(data)}可能导致不必要的组件重渲染,建议改用数据的唯一标识(如时间戳、数据ID),或仅在数据结构变化时触发重绘。


内容的提问来源于Stack Exchange,提问作者Codder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 05:53:21