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

如何用Chart.js实现点击环形图扇区将其中心旋转至起始0度位置

实现方案

完整代码示例

// 需先安装并注册Chart.js
import { Chart, ChartType, registerables } from 'chart.js';
Chart.register(...registerables);

const data = {
  datasets: [
    {
      label: 'My First Dataset',
      data: [300, 50, 100], // 支持动态修改
      backgroundColor: ['rgb(255, 99, 132)', 'rgb(54, 162, 235)', 'rgb(255, 205, 86)'],
      hoverOffset: 4,
    },
  ],
};

const config = {
  type: 'doughnut' as ChartType,
  data,
  options: {
    responsive: true,
    rotation: 0, // 初始旋转角度,默认值为0
    plugins: {
      legend: {
        position: 'bottom' as any,
        // 点击图例触发旋转
        onClick: (e, legendItem, legend) => {
          const chart = legend.chart;
          const dataset = chart.data.datasets[legendItem.datasetIndex];
          const targetIndex = legendItem.index;

          // 计算所有数据总和
          const total = dataset.data.reduce((sum, val) => sum + (val as number), 0);
          // 计算目标扇区之前所有数据累加的角度
          let preSum = 0;
          for (let i = 0; i < targetIndex; i++) {
            preSum += dataset.data[i] as number;
          }
          const preTotalAngle = (preSum / total) * 2 * Math.PI;
          // 计算当前扇区的半角
          const currentHalfAngle = ((dataset.data[targetIndex] as number) / total) * Math.PI;
          // 计算当前扇区中心点的绝对角度
          const centerAngle = preTotalAngle + currentHalfAngle + (chart.options.rotation as number);
          // 计算目标旋转值,让中心点对齐0度(12点钟方向)
          const targetRotation = -centerAngle;

          // 更新配置并重绘,可自定义动画效果
          chart.options.rotation = targetRotation;
          chart.update(); // 带默认过渡动画,不需要动画传参'none'即可

          // 如需保留默认点击图例隐藏扇区的逻辑,可取消注释下行
          // chart.toggleDataVisibility(targetIndex);
        }
      },
      title: {
        display: true,
        text: 'Chart.js Doughnut Chart',
      },
    },
    // 点击扇区本身也触发旋转,不需要可删除
    onClick: (e, elements) => {
      if (!elements.length) return;
      const { datasetIndex, index: targetIndex } = elements[0];
      const chart = e.chart;
      const dataset = chart.data.datasets[datasetIndex];

      const total = dataset.data.reduce((sum, val) => sum + (val as number), 0);
      let preSum = 0;
      for (let i = 0; i < targetIndex; i++) {
        preSum += dataset.data[i] as number;
      }
      const preTotalAngle = (preSum / total) * 2 * Math.PI;
      const currentHalfAngle = ((dataset.data[targetIndex] as number) / total) * Math.PI;
      const centerAngle = preTotalAngle + currentHalfAngle + (chart.options.rotation as number);
      const targetRotation = -centerAngle;

      chart.options.rotation = targetRotation;
      chart.update();
    }
  },
};

// 初始化图表,需提前在页面定义id为myChart的canvas元素
new Chart(
  document.getElementById('myChart') as HTMLCanvasElement,
  config
);

核心逻辑说明

  • Chart.js环形图默认以12点钟方向为rotation=0的起始位置,按顺时针方向绘制,单条数据对应的角度为(当前值 / 所有数据总和) * 2π
  • 扇区中心点角度 = 目标扇区之前所有数据的总角度 + 当前扇区角度的一半 + 当前已有的rotation值
  • 要让扇区中心对齐0度位置,只需将rotation设置为负的中心点角度即可
  • 代码兼容动态数据集:每次点击都会实时读取当前图表的数据集做计算,数据动态更新后功能不受影响

内容的提问来源于stack exchange,提问作者Rômulo Argolo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 13:15:03