Chart.js 饼图
在 React 项目中使用 Chart.js 创建饼图(Pie Chart)是一种常见的数据可视化方式,适合展示数据的比例或分布情况,如市场份额、投票结果等。结合 react-chartjs-2
库,饼图可以通过 React 组件化方式快速实现。本文以中文讲解 Chart.js 饼图的创建过程,涵盖基本用法、动态数据、样式定制、与 React Router 和 Tailwind CSS 的结合,以及注意事项,力求简洁清晰,并提供实用示例,同时避免与之前的环形图讲解重复。
1. 饼图概述
饼图(Pie Chart)是一种圆形图表,将数据分成扇形区域,展示各部分的占比。与环形图(Doughnut Chart)的主要区别是饼图没有中心空洞,呈现完整的圆形。Chart.js 的饼图支持:
- 多数据集:显示多组数据(多饼图)。
- 交互效果:支持悬停提示、点击事件。
- 响应式:自动适配容器大小。
- 高度可定制:调整颜色、边框、标签、动画等。
在 React 中,使用 react-chartjs-2
的 <Pie />
组件渲染饼图。
2. 基本饼图实现
以下是在 React 中使用 Chart.js 创建一个简单饼图的示例,展示类别数据的占比。
示例代码
import { Pie } from 'react-chartjs-2';
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';
// 注册必要模块
ChartJS.register(ArcElement, Tooltip, Legend);
function PieChart() {
// 数据配置
const data = {
labels: ['手机', '电脑', '平板', '其他'],
datasets: [
{
label: '设备销量占比',
data: [300, 150, 100, 50],
backgroundColor: [
'rgba(255, 99, 132, 0.6)', // 红色
'rgba(54, 162, 235, 0.6)', // 蓝色
'rgba(255, 206, 86, 0.6)', // 黄色
'rgba(75, 192, 192, 0.6)', // 青色
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
],
borderWidth: 1,
},
],
};
// 选项配置
const options = {
responsive: true,
plugins: {
legend: {
position: 'right', // 图例位置
labels: { font: { size: 12 } },
},
tooltip: {
backgroundColor: '#1f2937', // 提示框背景
callbacks: {
label: (context) => {
const label = context.label || '';
const value = context.raw;
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return `${label}: ${value} (${percentage}%)`;
},
},
},
title: {
display: true,
text: '2025 年设备销量占比',
font: { size: 16 },
},
},
};
return (
<div className="w-full max-w-md mx-auto p-6 bg-white rounded-lg shadow-md">
<Pie data={data} options={options} />
</div>
);
}
export default PieChart;
说明
- 注册模块:
ArcElement
:饼图的核心元素。Tooltip
、Legend
:提供交互和图例支持。- 数据(data):
labels
:定义每个扇区的名称(如设备类型)。datasets.data
:每个扇区的数据值。backgroundColor
/borderColor
:设置扇区颜色和边框。- 选项(options):
responsive: true
:适配容器大小。tooltip.callbacks.label
:自定义提示框,显示数值和百分比。legend.position
:控制图例位置(如'right'
)。- 容器:使用 Tailwind CSS 类(如
bg-white
、rounded-lg
)美化容器。
3. 多数据集饼图
饼图支持多个数据集,通常显示为多个并排的饼图,适合比较不同组的分布。
示例:多数据集饼图
function MultiPieChart() {
const data = {
labels: ['手机', '电脑', '平板'],
datasets: [
{
label: '2024 年销量',
data: [300, 150, 100],
backgroundColor: ['#ff6384', '#36a2eb', '#ffce56'],
borderWidth: 1,
},
{
label: '2025 年销量',
data: [350, 180, 120],
backgroundColor: ['#ff9f40', '#4bc0c0', '#9966ff'],
borderWidth: 1,
},
],
};
const options = {
responsive: true,
plugins: {
legend: { position: 'top' },
title: { display: true, text: '2024 vs 2025 年设备销量' },
},
};
return (
<div className="w-full max-w-lg mx-auto p-6 bg-white rounded-lg shadow-md">
<Pie data={data} options={options} />
</div>
);
}
说明
- 多数据集:每个
dataset
生成一个饼图,颜色区分不同年份。 - 布局:Chart.js 默认将多个饼图并排显示(需足够容器宽度)。
- 应用场景:对比多组数据的比例分布。
4. 动态数据更新
结合 React 的 useState
和 useEffect
Hooks,实现饼图的动态更新,适合实时数据展示。
示例:动态饼图
import { useState, useEffect } from 'react';
import { Pie } from 'react-chartjs-2';
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';
ChartJS.register(ArcElement, Tooltip, Legend);
function DynamicPieChart() {
const [data, setData] = useState({
labels: ['手机', '电脑', '平板'],
datasets: [
{
label: '实时销量',
data: [200, 100, 150],
backgroundColor: ['#ff6384', '#36a2eb', '#ffce56'],
borderWidth: 1,
},
],
});
useEffect(() => {
const interval = setInterval(() => {
setData(prev => ({
...prev,
datasets: [
{
...prev.datasets[0],
data: prev.datasets[0].data.map(() => Math.floor(Math.random() * 200) + 50),
},
],
}));
}, 3000); // 每 3 秒更新
return () => clearInterval(interval);
}, []);
const options = {
responsive: true,
plugins: {
legend: { position: 'top' },
title: { display: true, text: '实时设备销量占比' },
},
};
return (
<div className="w-full max-w-md mx-auto p-6 bg-white rounded-lg shadow-md">
<Pie data={data} options={options} />
</div>
);
}
说明
- 动态更新:
useEffect
每 3 秒生成随机数据,更新饼图。 - 性能优化:可用
useMemo
缓存data
和options
:
const memoizedData = useMemo(() => data, [data]);
- 应用场景:实时监控销量、流量占比等。
5. 与 React Router 结合
将饼图嵌入 React Router 页面,适合构建数据仪表盘。
示例
import { Routes, Route, NavLink } from 'react-router-dom';
import PieChart from './PieChart';
import MultiPieChart from './MultiPieChart';
function App() {
return (
<div className="p-6">
<nav className="mb-6 space-x-4">
<NavLink
to="/pie"
className={({ isActive }) =>
isActive ? 'text-blue-500 font-bold' : 'text-gray-500'
}
>
标准饼图
</NavLink>
<NavLink
to="/multi-pie"
className={({ isActive }) =>
isActive ? 'text-blue-500 font-bold' : 'text-gray-500'
}
>
多数据集饼图
</NavLink>
</nav>
<Routes>
<Route path="/pie" element={<PieChart />} />
<Route path="/multi-pie" element={<MultiPieChart />} />
</Routes>
</div>
);
}
说明
- NavLink:切换不同饼图页面,动态添加激活样式。
- Routes:映射饼图组件到路由路径。
6. 与 Tailwind CSS 结合
饼图渲染在 Canvas 上,外部容器可用 Tailwind CSS 美化。
示例
function PieChart() {
const data = { /* 同上 */ };
const options = { /* 同上 */ };
return (
<div className="bg-white p-6 rounded-lg shadow-md max-w-md mx-auto">
<h2 className="text-xl font-semibold mb-4 text-center">设备销量分布</h2>
<Pie data={data} options={options} />
</div>
);
}
说明
- 容器样式:Tailwind 类(如
bg-white
、rounded-lg
)美化容器。 - Canvas 样式:饼图内部样式由
data
和options
控制。
7. 自定义饼图样式
通过 options
和 data
自定义饼图的外观。
示例:自定义样式
const options = {
responsive: true,
plugins: {
legend: {
position: 'bottom',
labels: { font: { size: 12 }, boxWidth: 20 },
},
tooltip: {
backgroundColor: '#111827',
callbacks: {
label: (context) => {
const label = context.label || '';
const value = context.raw;
const total = context.dataset.data.reduce((a, b) => a + b, 0);
return `${label}: ${value} (${((value / total) * 100).toFixed(1)}%)`;
},
},
},
title: { display: true, text: '自定义饼图', font: { size: 16 } },
},
rotation: 30, // 旋转 30 度
animation: {
animateRotate: true, // 旋转动画
animateScale: true, // 缩放动画
},
};
说明
- 旋转:
rotation
设置饼图起始角度。 - 动画:
animation
控制旋转和缩放效果。 - Tooltip:自定义提示框显示百分比。
- Legend:调整图例样式,如大小和位置。
8. 注意事项
- 模块注册:
- 确保注册
ArcElement
,否则报错(如“Arc is not a registered element”)。
- 数据格式:
labels
和datasets.data
长度必须一致。- 数据值应为正数,避免负值或空数据。
- 性能优化:
- 使用
useMemo
缓存data
和options
:jsx const memoizedData = useMemo(() => data, [data]);
- 动态更新时限制数据量,避免性能问题。
- 容器尺寸:
- 饼图适合较小容器(如
max-w-md
),避免过大影响美观。 - 可设置
options.maintainAspectRatio: false
调整尺寸:jsx options: { maintainAspectRatio: false, height: 300 }
- 饼图 vs 环形图:
- 饼图(
cutout: 0%
)为实心圆,环形图(cutout: 50%
)有中心空洞。 - 若需空洞效果,可设置
cutout
属性。
- 调试:
- 检查浏览器开发者工具,确保 Canvas 渲染正常。
- 验证
data
和options
格式,排除配置错误。
9. 资源
- Chart.js 饼图文档:https://www.chartjs.org/docs/latest/charts/doughnut.html#pie
- react-chartjs-2 示例:https://react-chartjs-2.js.org/examples/pie-chart
- 中文社区:搜索“Chart.js 饼图 中文教程”或参考掘金、知乎。
如果需要更详细的讲解(如多饼图配置、动画效果、交互优化或与 Sass 集成),请告诉我!