Chart.js甜甜圈图表中心文字无法居中显示问题求助
解决React中Chart.js甜甜圈图表中心文字不居中的问题
问题排查
你的代码存在以下核心问题,导致文字无法正确居中且显示内容错误:
- 坐标计算错误:通过
chart.chartArea计算的坐标不一定是甜甜圈的实际中心,Chart.js提供了更可靠的中心坐标获取方式。 - options复用问题:三个图表共用同一个
options对象,导致所有图表都显示input1的值,而非各自对应的数据。 - font格式不完整:
ctx.font = 'bolder 24px'缺少字体族定义,可能导致浏览器渲染异常。 - JSX语法错误:返回的JSX中使用了转义的
<和>,应直接使用正常的HTML标签语法。
解决方案
- 获取精确中心坐标:使用
chart.getDatasetMeta(0).data[0].center获取甜甜圈的精确中心,这是Chart.js内置的圆弧中心获取方法。 - 独立配置每个图表:为每个图表创建专属的options,确保显示对应的数据。
- 完善字体属性:补充字体族,比如
'bolder 24px Arial'。 - 修正JSX语法:将转义标签替换为正常的
<>。
修正后的完整代码
import React, { useEffect, useState, useMemo } from 'react' import { Chart as ChartJS, ArcElement, Tooltip } from 'chart.js'; import { Doughnut } from 'react-chartjs-2'; ChartJS.register(ArcElement, Tooltip); export default function Roundedstats() { const [input1, setInput1] = useState(0); const [input2, setInput2] = useState(0); const [inputd1, setInputd1] = useState(0); const [inputd2, setInputd2] = useState(0); const [inputd3, setInputd3] = useState(0); const [inputd4, setInputd4] = useState(0); const [count, setCount] = useState([0, 0, 0]); const targetValue = useMemo(() => [input1, inputd1, inputd3], [input1, inputd1, inputd3]); useEffect(() => { const inputValue = 70; const inputValue1 = 30; const inputValue2 = 60; setInput1(inputValue); setInput2(100 - inputValue); setInputd1(inputValue1); setInputd2(100 - inputValue1); setInputd3(inputValue2); setInputd4(100 - inputValue2); const durations = [5000, 5000, 5000]; const increment = targetValue.map((value, index) => Math.ceil(value / durations[index] * 10) ); const timeout = setTimeout(() => { setCount((prevCounts) => prevCounts.map((count, index) => count < targetValue[index] ? count + increment[index] : count ) ); }, 10); return () => clearTimeout(timeout) }, [count, targetValue]); const data = { datasets: [{ data: [input1, input2], backgroundColor: ['red', '#071952'], }] }; const data1 = { datasets: [{ data: [inputd1, inputd2], backgroundColor: ['#0BB230', '#071952'] }] }; const data2 = { datasets: [{ data: [inputd3, inputd4], backgroundColor: ['#F87700', '#071952'] }] }; // 动态生成每个图表的配置 const getChartOptions = (displayValue, textColor) => ({ responsive: true, cutout: '80%', layout: { padding: 20, }, borderWidth: 0, plugins: { tooltip: { enabled: true }, beforeDraw: (chart) => { const ctx = chart.ctx; const center = chart.getDatasetMeta(0).data[0].center; ctx.save(); ctx.font = 'bolder 24px Arial'; ctx.fillStyle = textColor; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(`${displayValue}`, center.x, center.y); ctx.restore(); }, }, }); return ( <div className="flex gap-4"> {/* Stat 1 */} <div className='flex flex-col px-2 pb-2 overflow-hidden border-2 border-black rounded-lg gap-y-4'> <Doughnut data={data} options={getChartOptions(input1, 'red')} /> <h1 className='text-xl font-extrabold text-center font-Inter'>No of Visitors</h1> </div> {/* Stat 2 */} <div className='flex flex-col px-2 pb-2 overflow-hidden border-2 border-black rounded-lg gap-y-4'> <Doughnut data={data1} options={getChartOptions(inputd1, '#0BB230')} /> <h1 className='text-xl font-extrabold text-center font-Inter'>No of Forms</h1> </div> {/* Stat 3 */} <div className='flex flex-col px-2 pb-2 overflow-hidden border-2 border-black rounded-lg gap-y-4'> <Doughnut data={data2} options={getChartOptions(inputd3, '#F87700')} /> <h1 className='text-xl font-extrabold text-center font-Inter'>No of Contracts made</h1> </div> </div> ) }
额外优化说明
- 新增
getChartOptions函数,通过传入显示值和文字颜色动态生成配置,避免重复代码。 - 修正
borderWidth的无效值,设置为0更合理。 - 外层添加
flex gap-4容器,让图表横向排列更美观(可按需调整)。
内容的提问来源于stack exchange,提问作者changembidar
相关产品推荐
相关产品推荐

