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

如何偏移Highcharts环形图(Donut Chart)数据标签以避免重叠

解决Highcharts环形图(Donut Pie)数据标签重叠问题

问题背景

环形图内圈展示3个销售渠道的花费金额,外圈展示销售类型(库存销售/预售),过滤掉值为0的数据点后,剩余数据标签仍存在重叠,全局调整distance或padding参数会同时移动所有标签,无法实现差异化区分。

可行解决方案

1. 给单个数据点设置自定义标签偏移

针对特定数据点单独配置标签的偏移参数,不用全局统一调整。先修改数据处理函数,在过滤空值后给需要调整的点添加dataLabels配置:

const filterAndAdjustLabels = (data: Highcharts.PointOptionsObject[]) => {
  return data.filter(point => point.y !== 0).map(point => {
    // 根据点名称判断,按需设置偏移
    if (point.name === '库存销售') {
      return {
        ...point,
        dataLabels: {
          distance: 25, // 向外偏移更多
          y: -6 // 垂直微调避免重叠
        }
      };
    } else if (point.name === '预售') {
      return {
        ...point,
        dataLabels: {
          distance: 15,
          y: 6
        }
      };
    }
    return point;
  });
};

然后在初始化图表的series中替换原有的filterEmptyData:

series: [<Highcharts.SeriesPieOptions>{
  name: 'Percentage',
  size: '40%',
  data: filterAndAdjustLabels(oGraphData.oTurnoverGraphData.arrData)
}, <Highcharts.SeriesPieOptions>{
  name: 'OrderType',
  size: '50%',
  innerSize: '80%',
  data: filterAndAdjustLabels(oGraphData.oTurnoverGraphData.arrOrderTypeData)
}]

2. 启用Highcharts内置的标签自动避让

利用Highcharts自带的标签避让机制,调整allowOverlap、crop和softConnector参数,让标签自动避开重叠:

plotOptions: {
  pie: {
    allowPointSelect: true,
    cursor: 'pointer',
    animation: false,
    dataLabels: {
      color: '#333333',
      enabled: true,
      connectorColor: 'black',
      formatter: fnFormatter,
      allowOverlap: false, // 开启自动避让
      crop: false, // 不裁剪超出图表范围的标签
      softConnector: true // 使用柔性连接线,适配标签偏移
    }
  }
}

3. 动态计算并调整标签位置(适合动态数据)

如果数据是动态生成的,无法提前预判哪些标签会重叠,可以在图表渲染完成后,通过render事件做碰撞检测并调整标签位置:

chart: {
  plotShadow: false,
  type: 'pie',
  backgroundColor: '#FCFCFC',
  height: 436,
  events: {
    click: function () {
      $('#turnoverPieChart').siblings().highcharts()
    },
    render: function() {
      const chart = this;
      // 获取所有数据标签
      const allLabels = chart.series.flatMap(series => 
        series.points.map(point => point.dataLabel)
      ).filter(label => label);

      // 遍历标签做碰撞检测
      allLabels.forEach((currentLabel, idx) => {
        const currentBox = currentLabel.getBBox();
        for (let i = idx + 1; i < allLabels.length; i++) {
          const compareLabel = allLabels[i];
          const compareBox = compareLabel.getBBox();

          // 判断两个标签是否重叠
          const isOverlap = 
            currentBox.x < compareBox.x + compareBox.width &&
            currentBox.x + currentBox.width > compareBox.x &&
            currentBox.y < compareBox.y + compareBox.height &&
            currentBox.y + currentBox.height > compareBox.y;

          if (isOverlap) {
            // 垂直偏移当前标签10px
            currentLabel.translate(0, 10);
            // 更新连接线路径
            if (currentLabel.connector) {
              currentLabel.connector.attr({ d: currentLabel.getConnectorPath() });
            }
          }
        }
      });
    }
  },
}

4. 简化标签内容减少宽度

如果标签内容过长是重叠的主要原因,可以简化标签显示内容,把详细信息放到tooltip中:

// 数据标签只显示核心信息
const labelFormatter = function () {
  return `${this.point.name}: ${number_format(this.point.percentage, 1)}%`;
};
// tooltip保留完整金额信息
const tooltipFormatter = function () {
  return `${this.point.name}: ${number_format(this.point.percentage, 2)} % <br> Amount: ${number_format(this.point.y, 0)} ${strCurrencyCode}`;
};

// 图表配置中分别引用
tooltip: {
  formatter: tooltipFormatter
},
plotOptions: {
  pie: {
    dataLabels: {
      // ...其他配置
      formatter: labelFormatter
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:24:52