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

如何自定义react-apexcharts饼图标签位置并实现悬停高亮?

React-ApexCharts 饼图标签分左右布局并保留原生交互

要实现饼图标签分左右显示且不丢失悬停高亮的原生交互,不要自行构建独立的标签区域,而是利用 ApexCharts 原生的 dataLabels 配置来动态控制每个标签的位置,这样就能完整保留默认的交互效果。

核心思路

通过 dataLabels.custom 函数为每个标签单独设置偏移量,根据数据项的位置(或角度)将一半标签左移、另一半右移,同时保留原生 dataLabels 的关联交互。

方案1:按数据项数量拆分左右标签

适合数据项数量明确,希望前半部分标签在左、后半部分在右的场景:

import ReactApexChart from 'react-apexcharts';

const SplitLabelPieChart = () => {
  // 示例数据
  const chartData = [
    { name: '渠道1', value: 35 },
    { name: '渠道2', value: 20 },
    { name: '渠道3', value: 25 },
    { name: '渠道4', value: 20 },
  ];
  
  // 计算拆分索引:前一半左,后一半右
  const splitIndex = Math.floor(chartData.length / 2);

  const chartOptions = {
    chart: {
      type: 'pie',
      width: 700,
      height: 450,
    },
    series: chartData.map(item => item.value),
    labels: chartData.map(item => item.name),
    dataLabels: {
      enabled: true,
      // 自定义每个标签的位置和样式
      custom: ({ seriesIndex }) => {
        const isLeftLabel = seriesIndex < splitIndex;
        return {
          offsetX: isLeftLabel ? -140 : 140, // 左右偏移量,根据图表宽度调整
          offsetY: 0,
          style: {
            fontSize: '13px',
            fontWeight: '500',
          }
        };
      },
      // 自定义标签显示内容
      formatter: (val, opts) => {
        return `${opts.w.globals.labels[opts.seriesIndex]}: ${val}%`;
      },
    },
    // 隐藏默认图例,用dataLabels作为标签
    legend: {
      enabled: false,
    },
    // 保留 tooltip 交互
    tooltip: {
      enabled: true,
      marker: { show: true },
    },
  };

  return (
    <div className="pie-chart-container">
      <ReactApexChart 
        options={chartOptions} 
        series={chartOptions.series} 
        type="pie" 
      />
    </div>
  );
};

export default SplitLabelPieChart;

方案2:按饼图角度拆分左右标签

更贴合饼图视觉布局,上半圆(0-180度)的标签在左侧,下半圆(180-360度)的标签在右侧:

import ReactApexChart from 'react-apexcharts';

const AngleSplitPieChart = () => {
  const chartData = [
    { name: '产品A', value: 30 },
    { name: '产品B', value: 25 },
    { name: '产品C', value: 20 },
    { name: '产品D', value: 25 },
  ];

  // 计算每个数据项对应的角度范围,判断标签位置
  const totalValue = chartData.reduce((sum, item) => sum + item.value, 0);
  let currentStartAngle = 0;
  const labelPositionMap = chartData.map(item => {
    const itemAngle = (item.value / totalValue) * 360;
    // 取数据项的中间角度判断左右
    const midAngle = currentStartAngle + itemAngle / 2;
    const isLeftLabel = midAngle < 180;
    currentStartAngle += itemAngle;
    return isLeftLabel;
  });

  const chartOptions = {
    chart: {
      type: 'pie',
      width: 700,
      height: 450,
    },
    series: chartData.map(item => item.value),
    labels: chartData.map(item => item.name),
    dataLabels: {
      enabled: true,
      custom: ({ seriesIndex }) => {
        const isLeftLabel = labelPositionMap[seriesIndex];
        return {
          offsetX: isLeftLabel ? -150 : 150,
          offsetY: 0,
          style: {
            fontSize: '13px',
            color: isLeftLabel ? '#333' : '#333',
          }
        };
      },
      formatter: (val, opts) => {
        return `${opts.w.globals.labels[opts.seriesIndex]}: ${val}%`;
      },
    },
    legend: {
      enabled: false,
    },
    tooltip: {
      enabled: true,
    },
  };

  return (
    <div className="pie-chart-container">
      <ReactApexChart 
        options={chartOptions} 
        series={chartOptions.series} 
        type="pie" 
      />
    </div>
  );
};

export default AngleSplitPieChart;

关键说明

  • 两种方案都基于 ApexCharts 原生的 dataLabels,因此完全保留了鼠标悬停标签时对应饼图区域高亮、悬停饼图区域时标签同步响应的原生交互。
  • 调整 offsetX 的数值可以适配不同的图表宽度,确保标签不会被截断或重叠。
  • 如果需要更复杂的标签样式,可以在 custom 返回的 style 对象中添加更多 CSS 属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 07:40:37