Chart.js饼图与环形图内部文本显示问题咨询
react-chartjs-2 饼图/环形图问题修复方案
1. 扇区差异化文本展示 + TypeScript类型报错解决
差异化文本配置
chartjs-plugin-datalabels的formatter回调支持按单个数据点返回不同格式,回调第二个参数context携带当前数据点索引、所属数据集等元信息,直接按规则判断返回值即可,不需要做复杂的全局配置拆分。
比如数据集为[11,200]、要求第一个点显示11%、第二个点显示原始值200的场景,直接按索引判断:
formatter: (value:any, context:Context) => { // 索引0对应第一个数据点,返回百分号格式 if(context.dataIndex === 0) return `${Math.floor(value)}%` // 其余数据点返回原始数值 return value }
判断规则不局限于索引,也可以根据数值大小、数据集自定义字段等任意维度调整,逻辑完全自定义。
TS类型报错修复
报错根因是react-chartjs-2的默认类型定义没有自动合并第三方插件的配置字段,TS识别不到plugins.datalabels属性,两种方案选一个即可:
- 快速修复:给options加类型断言
import type { ChartOptions } from 'chart.js'; // 原有配置不变,末尾加类型断言 export const options = { responsive: true, maintainAspectRatio: false, plugins: { // 原有datalabels、title、legend配置不变 } } as ChartOptions<'pie'>; - 长期修复:扩展模块类型,在项目全局类型声明文件中添加如下代码,后续所有组件都不会再报同类错误:
import type { ChartType } from 'chart.js'; import type { ChartDataLabelsOptions } from 'chartjs-plugin-datalabels'; declare module 'chart.js' { interface PluginOptionsByType<TType extends ChartType> { datalabels?: ChartDataLabelsOptions; } }
2. 环形图中心自定义文本实现
网上流传的旧方案大多是针对chart.js v2版本的,v3/v4版本架构调整后会失效。直接用chart.js自带的自定义插件能力,在图表绘制完成后通过canvas API把文本画在中心位置即可,兼容性最好。
完整实现代码:
import { Chart, ArcElement, Tooltip, Legend } from 'chart.js'; import ChartDataLabels,{Context} from 'chartjs-plugin-datalabels'; import { Doughnut } from 'react-chartjs-2'; Chart.register(ArcElement, Tooltip, Legend, ChartDataLabels); // 中心文本绘制插件 const centerTextPlugin = { id: 'doughnutCenterText', afterDraw: (chart: Chart) => { const ctx = chart.ctx; // 计算环形图中心坐标 const { left, top, width, height } = chart.chartArea; const centerX = left + width / 2; const centerY = top + height / 2; ctx.save(); // 自定义文本样式 ctx.font = 'bold 20px system-ui'; ctx.fillStyle = '#1f2937'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; // 替换为需要显示的文本,支持动态读取chart绑定的自定义属性 ctx.fillText('自定义中心内容', centerX, centerY); ctx.restore(); } }; // 注册插件 Chart.register(centerTextPlugin); export const options = { responsive: true, maintainAspectRatio: false, plugins: { datalabels: { formatter: (value:any, context:Context) => { if(context.dataIndex === 0) return `${Math.floor(value)}%` return value }, color:"white", font: { size: 16, weight:'bold' } }, title: { display: true }, legend: { display: false }, }, }; function MyChart(){ return <Doughnut data={dataChart} options={options} /> }
如果需要动态更新中心文本,只需要把文本存在组件state中,在插件里读取chart实例上挂载的自定义属性即可,适配动态数据场景。
内容的提问来源于stack exchange,提问作者Sai Krishnadas
相关产品推荐
相关产品推荐

