如何在 Chart.js 饼图中心动态显示数值文本

11次阅读

如何在 Chart.js 饼图中心动态显示数值文本

本文详解如何在 react 中使用 chart.js + react-chartjs-2 在环形图(doughnut)中心精准绘制动态数值文本,解决因插件注册位置错误导致的文本不显示问题,并提供可直接运行的完整实现方案。

在 Chart.js(v3+)中为 Doughnut 图表添加中心文本,不能将自定义绘图逻辑直接写在 options.plugins 内联对象——这是原代码失效的根本原因。Chart.js v3 的插件系统要求:插件必须作为独立对象定义,并通过 组件的 plugins prop 显式传入,而非嵌套在 options.plugins 里(后者仅用于配置内置插件,如 tooltip、legend)。

以下是修正后的关键步骤与完整实践代码:

✅ 正确做法:分离插件定义 + 正确传入

// 1. 定义独立插件(注意:必须有唯一 id) const centerTextPlugin = {   id: 'centerText',   beforeDraw: (chart) => {     const { ctx, chartArea: { left, top, right, bottom } } = chart;     const centerX = left + (right - left) / 2;     const centerY = top + (bottom - top) / 2;      ctx.save();     ctx.font = 'bold 28px Inter, sans-serif'; // 推荐使用系统字体     ctx.fillStyle = '#E53E3E';     ctx.textAlign = 'center';     ctx.textBaseline = 'middle';     ctx.fillText(`${Math.round(chart.data.datasets[0].data[0])}%`, centerX, centerY);     ctx.restore();   } };  // 2. options 中 plugins 保持为空对象(或仅含配置项) const doughnutOptions = {   responsive: true,   cutout: '75%',   layout: { padding: 16 },   plugins: {     // ⚠️ 这里只放配置(如 tooltip.enabled = false),不放函数!   } };

✅ 在组件中正确使用

? 常见陷阱与注意事项

  • chart.ctx 安全性:确保在 beforedraw 钩子中操作 ctx,此时 canvas 上下文已就绪;避免在 afterDraw 或其他钩子中误用。
  • 动态数据同步:文本内容(如 ${input1})需随 data 实时更新。本例中 input1 是响应式 state,插件内直接读取 chart.data.datasets[0].data[0] 更健壮(自动跟随数据变化)。
  • 字体与抗锯齿:添加 ctx.lineJoin = ’round’ 和 ctx.imageSmoothingQuality = ‘high’ 可提升文本渲染质量。
  • 多图表复用:若多个 Doughnut 需不同中心文本,可将插件封装为工厂函数:
    const createCenterTextPlugin = (getText: (chart: Chart) => string) => ({   id: 'dynamicCenterText',   beforeDraw: (chart: Chart) => {     const ctx = chart.ctx;     const { left, top, right, bottom } = chart.chartArea;     ctx.save();     ctx.font = 'bold 24px sans-serif';     ctx.fillStyle = '#2D3748';     ctx.textAlign = 'center';     ctx.textBaseline = 'middle';     ctx.fillText(getText(chart), (left + right) / 2, (top + bottom) / 2);     ctx.restore();   } }); // 使用:plugins={[createCenterTextPlugin((c) => `${c.data.datasets[0].data[0]}%`)]}

✅ 最终效果保障

  • 文本始终居中(利用 textAlign=’center’ + textBaseline=’middle’ + 准确计算中心坐标);
  • 动态响应数据变化(state 更新 → re-render → 插件重新执行);
  • 不干扰其他图表功能(tooltip、动画、响应式等均正常)。

通过将插件逻辑解耦并严格遵循 Chart.js v3 插件注入规范,即可稳定、高效地在环形图中心渲染任意文本——这是生产环境推荐的标准实践。

text=ZqhQzanResources