You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chart.js甜甜圈图表中心文字无法居中显示问题求助

解决React中Chart.js甜甜圈图表中心文字不居中的问题

问题排查

你的代码存在以下核心问题,导致文字无法正确居中且显示内容错误:

  • 坐标计算错误:通过chart.chartArea计算的坐标不一定是甜甜圈的实际中心,Chart.js提供了更可靠的中心坐标获取方式。
  • options复用问题:三个图表共用同一个options对象,导致所有图表都显示input1的值,而非各自对应的数据。
  • font格式不完整:ctx.font = 'bolder 24px'缺少字体族定义,可能导致浏览器渲染异常。
  • JSX语法错误:返回的JSX中使用了转义的<和>,应直接使用正常的HTML标签语法。

解决方案

  1. 获取精确中心坐标:使用chart.getDatasetMeta(0).data[0].center获取甜甜圈的精确中心,这是Chart.js内置的圆弧中心获取方法。
  2. 独立配置每个图表:为每个图表创建专属的options,确保显示对应的数据。
  3. 完善字体属性:补充字体族,比如'bolder 24px Arial'。
  4. 修正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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 15:07:32