如何自定义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
相关产品推荐
相关产品推荐

