Highcharts:将数据标签放置在饼图各部分的中间
Highcharts: Placement of data labels in the middle of sections of Pie Chart
我希望饼图的数据标签显示在各部分的中间,而不考虑:
- 该段是否已切片
- 是否提到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().
我希望饼图的数据标签显示在各部分的中间,而不考虑:
- 该段是否已切片
- 是否提到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().