Chart.js 柱形图

在 React 项目中使用 Chart.js 创建柱状图(Bar Chart)是一种常见的数据可视化方式,适合展示分类数据的对比,如销量、评分等。结合 react-chartjs-2 库,柱状图可以在 React 中以组件化方式快速实现。本文以中文讲解 Chart.js 柱状图的创建过程,涵盖基本用法、动态数据、样式定制、与 React Router 和 Tailwind CSS 的结合,以及注意事项,力求简洁清晰,避免重复之前的内容,并提供实用示例。


1. 柱状图概述

柱状图(Bar Chart)通过垂直或水平的柱子展示不同类别的数据,适用于比较不同组的数据大小。Chart.js 的柱状图支持:

  • 多数据集:展示多个类别的数据(如不同年份的销量)。
  • 堆叠柱状图:将多个数据集堆叠显示。
  • 响应式:自动适配容器大小。
  • 自定义样式:调整颜色、边框、标签等。

在 React 中,使用 react-chartjs-2<Bar /> 组件渲染柱状图。


2. 基本柱状图实现

以下是在 React 中使用 Chart.js 创建一个简单柱状图的示例。

示例代码

import { Bar } from 'react-chartjs-2';
import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend } from 'chart.js';

// 注册必要模块
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);

function BarChart() {
  // 数据配置
  const data = {
    labels: ['一月', '二月', '三月', '四月', '五月'],
    datasets: [
      {
        label: '2025 年销量',
        data: [65, 59, 80, 81, 56],
        backgroundColor: 'rgba(59, 130, 246, 0.5)', // 蓝色填充
        borderColor: 'rgba(59, 130, 246, 1)', // 边框颜色
        borderWidth: 1,
      },
    ],
  };

  // 选项配置
  const options = {
    responsive: true,
    plugins: {
      legend: {
        position: 'top', // 图例位置
      },
      title: {
        display: true,
        text: '2025 年月度销量柱状图',
      },
      tooltip: {
        backgroundColor: '#1f2937', // 提示框背景
        titleFont: { size: 14 },
      },
    },
    scales: {
      y: {
        beginAtZero: true,
        title: { display: true, text: '销量 (单位)' },
        grid: { color: '#e5e7eb' }, // 浅灰色网格
      },
      x: {
        title: { display: true, text: '月份' },
      },
    },
  };

  return (
    <div className="w-full max-w-3xl mx-auto p-6 bg-white rounded-lg shadow-md">
      <Bar data={data} options={options} />
    </div>
  );
}

export default BarChart;

说明

  • 注册模块BarElementCategoryScale 等是柱状图必需的模块。
  • 数据(data)
  • labels:X 轴标签(如月份)。
  • datasets:数据集,包含标签、数据点、颜色等。
  • 选项(options)
  • responsive: true:确保图表适配容器。
  • plugins:配置图例(legend)、标题(title)、提示框(tooltip)。
  • scales:自定义 X/Y 轴,例如添加标题或调整网格。
  • 容器:使用 Tailwind CSS 类(如 bg-whiterounded-lg)美化图表容器。

3. 多数据集柱状图

柱状图支持多个数据集,用于比较不同类别的数据。

示例:多数据集柱状图

function MultiBarChart() {
  const data = {
    labels: ['一月', '二月', '三月', '四月'],
    datasets: [
      {
        label: '2024 年销量',
        data: [50, 45, 60, 55],
        backgroundColor: 'rgba(59, 130, 246, 0.5)',
        borderColor: 'rgba(59, 130, 246, 1)',
        borderWidth: 1,
      },
      {
        label: '2025 年销量',
        data: [65, 59, 80, 81],
        backgroundColor: 'rgba(236, 72, 153, 0.5)',
        borderColor: 'rgba(236, 72, 153, 1)',
        borderWidth: 1,
      },
    ],
  };

  const options = {
    responsive: true,
    plugins: {
      legend: { position: 'top' },
      title: { display: true, text: '年度销量对比' },
    },
    scales: {
      y: { beginAtZero: true, title: { display: true, text: '销量 (单位)' } },
    },
  };

  return (
    <div className="w-full max-w-3xl mx-auto p-6 bg-white rounded-lg shadow-md">
      <Bar data={data} options={options} />
    </div>
  );
}

说明

  • 多数据集:每个 dataset 表示一组柱子,不同颜色区分。
  • 并排显示:Chart.js 默认将多数据集的柱子并排显示。

4. 堆叠柱状图

通过设置 options.scales 中的 stacked 属性,实现堆叠柱状图。

示例:堆叠柱状图

function StackedBarChart() {
  const data = {
    labels: ['一月', '二月', '三月'],
    datasets: [
      {
        label: '产品 A',
        data: [20, 30, 25],
        backgroundColor: '#3b82f6',
      },
      {
        label: '产品 B',
        data: [30, 20, 35],
        backgroundColor: '#ec4899',
      },
    ],
  };

  const options = {
    responsive: true,
    scales: {
      x: { stacked: true }, // X 轴堆叠
      y: { stacked: true, beginAtZero: true }, // Y 轴堆叠
    },
    plugins: {
      legend: { position: 'top' },
      title: { display: true, text: '产品销量堆叠图' },
    },
  };

  return (
    <div className="w-full max-w-3xl mx-auto p-6 bg-white rounded-lg shadow-md">
      <Bar data={data} options={options} />
    </div>
  );
}

说明

  • 堆叠stacked: true 使柱子垂直堆叠,适合展示总和及各部分占比。
  • 应用场景:如按类别分解的总销量。

5. 动态数据更新

结合 React 的 useStateuseEffect Hooks,实现柱状图的动态更新。

示例:动态柱状图

import { useState, useEffect } from 'react';
import { Bar } from 'react-chartjs-2';
import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Title, Tooltip } from 'chart.js';

ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip);

function DynamicBarChart() {
  const [data, setData] = useState({
    labels: ['周一', '周二', '周三'],
    datasets: [
      {
        label: '访问量',
        data: [100, 150, 120],
        backgroundColor: 'rgba(34, 197, 94, 0.5)',
        borderColor: 'rgba(34, 197, 94, 1)',
        borderWidth: 1,
      },
    ],
  });

  useEffect(() => {
    const interval = setInterval(() => {
      setData(prev => ({
        ...prev,
        datasets: [
          {
            ...prev.datasets[0],
            data: prev.datasets[0].data.map(() => Math.floor(Math.random() * 200)),
          },
        ],
      }));
    }, 3000); // 每 3 秒更新
    return () => clearInterval(interval);
  }, []);

  const options = {
    responsive: true,
    plugins: { title: { display: true, text: '实时访问量' } },
  };

  return (
    <div className="w-full max-w-3xl mx-auto p-6 bg-white rounded-lg shadow-md">
      <Bar data={data} options={options} />
    </div>
  );
}

说明

  • 动态更新useEffect 每 3 秒生成随机数据,更新柱状图。
  • 性能优化:可用 useMemo 缓存 data
  const memoizedData = useMemo(() => data, [data]);

6. 与 React Router 结合

将柱状图组件嵌入 React Router 页面,适合数据仪表盘。

示例

import { Routes, Route, NavLink } from 'react-router-dom';
import BarChart from './BarChart';
import StackedBarChart from './StackedBarChart';

function App() {
  return (
    <div className="p-6">
      <nav className="mb-6 space-x-4">
        <NavLink
          to="/bar"
          className={({ isActive }) =>
            isActive ? 'text-blue-500 font-bold' : 'text-gray-500'
          }
        >
          标准柱状图
        </NavLink>
        <NavLink
          to="/stacked"
          className={({ isActive }) =>
            isActive ? 'text-blue-500 font-bold' : 'text-gray-500'
          }
        >
          堆叠柱状图
        </NavLink>
      </nav>
      <Routes>
        <Route path="/bar" element={<BarChart />} />
        <Route path="/stacked" element={<StackedBarChart />} />
      </Routes>
    </div>
  );
}

说明

  • NavLink:动态切换图表页面,添加激活样式。
  • Routes:映射不同柱状图组件。

7. 与 Tailwind CSS 结合

Chart.js 柱状图渲染在 Canvas 上,外部容器可用 Tailwind CSS 美化。

示例

function BarChart() {
  const data = { /* 同上 */ };
  const options = { /* 同上 */ };

  return (
    <div className="bg-white p-6 rounded-lg shadow-md max-w-3xl mx-auto">
      <h2 className="text-xl font-semibold mb-4 text-center">月度销量</h2>
      <Bar data={data} options={options} />
    </div>
  );
}

说明

  • 容器样式:Tailwind 类(如 p-6rounded-lg)美化容器。
  • Canvas 样式:柱状图内部样式由 Chart.js 的 dataoptions 控制。

8. 自定义柱状图样式

通过 optionsdata 自定义柱状图的外观。

示例:自定义样式

const options = {
  responsive: true,
  plugins: {
    legend: { position: 'bottom', labels: { font: { size: 12 } } },
    tooltip: { backgroundColor: '#111827', padding: 10 },
  },
  scales: {
    y: {
      beginAtZero: true,
      grid: { color: '#e5e7eb', lineWidth: 1 },
      ticks: { stepSize: 20 }, // Y 轴刻度间隔
    },
    x: { grid: { display: false } }, // 隐藏 X 轴网格
  },
  elements: {
    bar: {
      borderRadius: 4, // 柱子圆角
      borderSkipped: false, // 边框完整
    },
  },
};

说明

  • 柱子样式borderRadius 设置柱子圆角,borderSkipped 控制边框。
  • 网格和刻度:调整 scalesgridticks
  • 提示框:自定义 tooltip 样式。

9. 注意事项

  1. 模块注册
  • 确保注册 BarElementCategoryScaleLinearScale,否则报错(如“Category is not a registered scale”)。
  1. 数据格式
  • labelsdatasets.data 长度必须一致。
  • 避免空数据或无效值(如 null)。
  1. 性能优化
  • 使用 useMemo 缓存 dataoptions
    jsx const memoizedData = useMemo(() => data, [data]);
  • 动态更新时避免频繁渲染大数据。
  1. 容器尺寸
  • Canvas 需要显式宽高,可通过 CSS 或 options 设置:
    jsx options: { maintainAspectRatio: false, height: 400 }
  1. 调试
  • 检查浏览器开发者工具,确保 Canvas 渲染正常。
  • 验证 dataoptions 格式,排除配置错误。

10. 资源

  • Chart.js 官方文档:https://www.chartjs.org/docs/latest/charts/bar.html
  • react-chartjs-2 文档:https://react-chartjs-2.js.org/examples/bar-chart
  • 中文社区:搜索“Chart.js 柱状图 中文教程”或参考掘金、知乎。

如果需要更详细的讲解(如堆叠柱状图高级配置、插件集成或动态交互),请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注