Highcharts:将数据标签放置在饼图各部分的中间

Highcharts: Placement of data labels in the middle of sections of Pie Chart

我希望饼图的数据标签显示在各部分的中间,而不考虑:

  1. 该段是否已切片
  2. 是否提到plotOptions中的size属性

解决方案 1

为此,我尝试使用 plotOptions 的距离属性。我在图表的 load() 事件中从 series[0].points[0].shapeArgs.r 获得了半径。然后使用以下内容:

series[0].update({
    dataLabels: {
        distance: -(radius/2)
    }
});

http://jsfiddle.net/k94x958d/2/

但这带来了两个问题:饼图加载动画丢失,如果任何部分被切片,数据标签放置不正确

http://jsfiddle.net/k94x958d/3/

解决方案 2

为了解决动画问题,我尝试使用上述逻辑获取距离,然后在 Highcharts 库的重写 drawDataLabels() 方法中将其设置为系列[0]。options.dataLabels。但是没有用。

有什么方法可以实现将数据标签放置在饼图部分的中间,而不考虑大小、切片等?

这是一个很好的问题,我特别喜欢您使用图表半径(而不是使用固定值)计算数据标签距离的方法。

我与您的 fiddle 合作已有一段时间了。不幸的是,我不认为你问的是可能的

由于您要移动饼图切片部分的数据标签,使其位于该切片的中心,因此您需要向其中添加 slicedOffset 值数据标签的 distance 属性。

我曾想象过这样的事情:

events: {
  load: function() {
    var series = this.series[0],
        distance = series.points[0].shapeArgs.r / 2,
        pieOffset = this.options.plotOptions.pie.slicedOffset;
    $.each(series.points, function(index, value) {
      if (typeof value.sliced === "undefined") {
        value.update({
          dataLabels: { distance: -distance }
        });
      } else {
        value.update({
          dataLabels: { distance: -distance - pieOffset }
        });
      }
    });
  }
}

然而,没有任何改变。您似乎可以在系列级别(或整个饼图)定义数据标签的距离,但不能在点级别

根据 Highcharts API,您应该 能够像 plotOptions.series.dataLabels 一样为 series.data.dataLabels 设置任何属性(参见 http://api.highcharts.com/highcharts#series<pie>.data.dataLabels),但只有某些有效(例如,如果您为特定点的数据标签设置 rotation,则会显示,但不会显示 distance)。

这是你的 fiddle 的修改版本,其中包含我不成功的实验:http://jsfiddle.net/brightmatrix/k94x958d/5/

现在,解决您的其他项目关于系列在您更新时没有动画,我认为这可能是因为您正在加载事件中更新系列,并且不是之后通过单独的事件。有几个示例展示了如何使用 setData()setVisible() 来强制播放动画,但是当我更新 fiddle 中的 load 事件时,这些解决方案都不起作用。

以下是我研究的问题:

  • Highcharts loading animation after setdata

在这种情况下,也许您可​​以有一个 jQuery 事件(在您的图表选项之外)在页面加载时触发以强制播放动画。

希望这些信息对您有所帮助。我也希望其中一位 Highcharts 开发人员可以参与我的研究。

我们可以在加载事件中使用如下代码:

 series[0].update({
    animation: true,
    dataLabels: {
        distance: -(series[0].points[0].shapeArgs.r/2)
     }
 });

 _.each( series[0].points, function( point ) {
    var x = point.slicedTranslation.translateX + point.dataLabel.translateX,
        y = point.slicedTranslation.translateY + point.dataLabel.translateY;

    point.dataLabel.attr( {
        transform: 'translate(' + x + ',' + y + ')'
    } );
 });

以上代码解决了切片和大小的问题。调用 attr() 似乎可以保留动画。唯一仍然存在的问题是动画因调用 update() 而丢失。

[编辑] 由于切片而翻译数据标签的方式,有没有办法使用 attr() 将它们翻译到部分的中间?

[编辑] 解决了.. 把 animation: true 放在 update().