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

React中使用Chart.js实现环形图表内圆形排列标签的方法

在React中实现Chart.js环形图内圆形排列标签的解决方案

问题概述

需要在React项目中,基于Chart.js的环形(doughnut)图表实现环形内侧圆形排列的标签,尝试使用chartjs-plugin-datalabels但未成功,需明确可行方案及支持库。

核心问题分析

你当前代码的关键错误在于:generateLabels是Chart.js图例(legend)的配置项,并非chartjs-plugin-datalabels的数据标签定位逻辑,因此无法实现标签的圆形排列。数据标签的位置控制需要通过插件自身的配置参数实现。

可行方案及修正代码

依赖确认

确保已安装必要依赖:

npm install chart.js chartjs-plugin-datalabels react

修正后的完整代码

import React, { useEffect, useRef } from "react";
import Chart from "chart.js/auto";
import ChartDataLabels from "chartjs-plugin-datalabels";
import { MuiTooltip } from "../../components";

const Graph = () => {
  const chartRef = useRef(null);
  const chartInstance = useRef(null);
  let tooltip = false;

  useEffect(() => {
    const renderChart = () => {
      const ctx = chartRef.current.getContext("2d");

      if (chartInstance.current !== null) {
        chartInstance.current.destroy();
      }

      chartInstance.current = new Chart(ctx, {
        type: "doughnut",
        data: {
          labels: [
            "SHAPES STRATEGY",
            "BUILDS CULTURE BUILDS",
            "SCALES LEADERSHIP",
            "DRIVES EXECUTION",
          ],
          datasets: [
            {
              data: [25, 25, 25, 25],
              backgroundColor: ["rgb(55, 99, 132)", "rgb(75, 192, 192)", "rgb(255, 206, 86)", "rgb(255, 99, 132)"],
              borderColor: ["white", "white", "white", "white"],
              borderWidth: 2,
            },
          ],
        },
        options: {
          cutout: "65%",
          radius: "100%",
          rotation: -0.5 * Math.PI,
          plugins: {
            legend: { display: false },
            datalabels: {
              color: '#FFFFFF',
              font: { size: 12, weight: 'bold' },
              // 核心:通过scriptable函数动态计算每个标签的位置和旋转角度
              align: 'center',
              anchor: 'center',
              offset: function(context) {
                const chart = context.chart;
                // 定义标签所在的圆形半径(环形内侧区域)
                const labelRadius = (chart.innerRadius + chart.outerRadius) / 2 - 20;
                const index = context.dataIndex;
                const data = chart.data.datasets[0].data;
                const total = data.reduce((a, b) => a + b, 0);
                // 计算当前扇区的中心角度(转换为适配坐标的弧度)
                const cumulativeAngle = data.slice(0, index).reduce((a, b) => a + b, 0) / total * 2 * Math.PI;
                const currentAngle = cumulativeAngle + (data[index] / total * 2 * Math.PI) / 2 - Math.PI / 2;
                // 计算标签偏移量,实现圆形排列
                return {
                  x: labelRadius * Math.cos(currentAngle),
                  y: labelRadius * Math.sin(currentAngle)
                };
              },
              // 可选:让标签沿着圆弧旋转,视觉更贴合圆形布局
              rotation: function(context) {
                const index = context.dataIndex;
                const data = context.chart.data.datasets[0].data;
                const total = data.reduce((a, b) => a + b, 0);
                const cumulativeAngle = data.slice(0, index).reduce((a, b) => a + b, 0) / total * 2 * Math.PI;
                const currentAngle = cumulativeAngle + (data[index] / total * 2 * Math.PI) / 2;
                // 转换为Chart.js支持的角度值
                return (currentAngle * 180 / Math.PI) - 90;
              },
              formatter: (value, ctx) => ctx.chart.data.labels[ctx.dataIndex]
            },
          },
        },
        plugins: [ChartDataLabels],
      });
    };

    renderChart();

    return () => {
      if (chartInstance.current !== null) {
        chartInstance.current.destroy();
      }
    };
  }, []);

  return (
    <div style={{ marginLeft: "6rem", width: 700, height: 700, marginTop: "5rem" }}>
      <MuiTooltip title={tooltip} position="bottom">
        <canvas ref={chartRef}></canvas>
      </MuiTooltip>
    </div>
  );
};

export default Graph;

关键改动说明

  1. 移除无效配置:删除了generateLabels配置,该配置仅用于自定义图例项,与数据标签定位无关。
  2. 动态位置计算:通过offset的可脚本化函数,根据每个扇区的角度计算标签坐标,使其沿环形内侧的圆形轨迹排列。
  3. 标签旋转优化:添加rotation函数,让标签文本沿圆弧方向旋转,视觉上更贴合圆形布局(可根据需求移除)。
  4. 视觉区分优化:为每个扇区添加不同背景色,便于直观区分(原代码仅设置单一背景色)。

支持的库

  • chartjs-plugin-datalabels:官方推荐的数据标签插件,通过上述配置即可实现环形内圆形排列标签,无需额外引入其他库。
  • 若需更复杂的标签排版(如多行文本、自定义形状),可基于Chart.js的自定义插件API实现,但chartjs-plugin-datalabels已能满足大部分场景需求。

内容的提问来源于stack exchange,提问作者Madhu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 00:00:37