在Highcharts饼图中旋转数据标签

4
我正在尝试旋转和定位Highcharts饼图中每个部分的数据标签,但感觉越陷越深,却没有接近解决方案。希望能得到一些提示或建议。
所需目标的示意图:
每个饼图中将有三个部分。我希望:
- 每个数据标签都被旋转,从而为每个部分创建一个中心线(由品红色线条说明); - 数据标签在段落中居中,无论字体大小如何。
有关如何开始此操作的建议,或者可以让我接近解决方案的示例?

$(function () {
 $('#container').highcharts({
  chart: {
   type: 'pie',
   backgroundColor: 'transparent',
   spacing: [0, 0, 0, 0],
   margin: [0, 0, 0, 0],
   events: {
    load: function() {
     $.each(this.series[0].data, function(index, point) {

      var degree = (point.angle * 180) / Math.PI;
      var rotation = 0;
      (degree < 0) && (degree += 360);

      // If the slice is in the left half, then rotate 180
      // so the text won't look upside down
      if (degree >= 90 && degree <= 270) {
       rotation = degree - 180;
       point.dataLabel.x = 0;
       point.dataLabel.y = 0;
       point.dataLabel.translateX = (point.labelPos[2] + point.labelPos[4]) / 2;
       point.dataLabel.translateY = (point.labelPos[3] + point.labelPos[5]) / 2;
      } else {
       point.dataLabel.x = 0;
       point.dataLabel.y = 0;
       rotation = degree - 180;
       point.dataLabel.translateX = (point.labelPos[2] + point.labelPos[4]) / 2;
       point.dataLabel.translateY = (point.labelPos[3] + point.labelPos[5]) / 2;
      }

      point.dataLabel.rotation = Math.floor(rotation);
      point.dataLabel.show();
      point.dataLabel.updateTransform();
     });
    }
   }
  },
  title: {
   text: null
  },
  yAxis: {
   title: {
    text: 'Total percent market share'
   }
  },
  plotOptions: {
   pie: {
    borderColor: 'rgb(243, 243, 243)',
    borderWidth: 2,
    shadow: false,
    center: ['50%', '50%'],
    colors: ['rgb(77, 196, 215)', 'rgb(50, 68, 132)', 'rgb(85, 119, 183)']
   }
  },
  tooltip: {
   enabled: false
  },
  series: [{
   type: 'pie',
   name: 'Votes',
   data: [
    ['Yes', 9],
    ['No', 5],
    ['Undecided', 2]
   ],
   size: '90%',
   dataLabels: {
    formatter: function () {
     return this.point.name;
    },
    color: 'white',
    connectorWidth: 0,
    distance: -80
   }
  }]
 });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 600px; width: 100%;"></div>


请提供一个现场演示,并展示您到目前为止所做的工作。 - Raein Hashemi
1
这是我能做到的最好了。http://jsfiddle.net/6cn6dtyj/ 你能分享一下你的进展吗? - Hristo Ivanov
添加了一个新的代码片段来分享我的工作进展。 - Brandon Durham
2个回答

3

Highcharts没有提供自动旋转饼状图数据标签的选项。您可以编写自定义函数来旋转数据标签。

以下是一个简单的示例,展示如何完成此操作:

var allY, angle1, angle2, angle3,
    rotate = function () {
        $.each(options.series, function (i, p) {
            angle1 = 0;
            angle2 = 0;
            angle3 = 0;
            allY = 0;
            $.each(p.data, function (i, p) {
                allY += p.y;
            });

            $.each(p.data, function (i, p) {
                angle2 = angle1 + p.y * 360 / (allY);
                angle3 = angle2 - p.y * 360 / (2 * allY);
                p.dataLabels.rotation = -90 + angle3;
                angle1 = angle2;
            });
        });
    };

首先我计算所有Y值的总和。然后我计算所有饼图块中间的角度。最后,我将数据标签旋转相同的角度。

例如: http://jsfiddle.net/izothep/j7as86gh/6/

类似话题: Highcharts中径向饼图数据标签


2
我发现旋转标签本身存在问题,因为在使用highcharts进行旋转时,它似乎围绕它们自己的轴旋转。为了获得最佳结果,您需要围绕饼图的原点旋转标签。为了实现这一点,我将绝对定位的div直接添加到饼图的顶部,并迭代点以根据百分比计算旋转。当然,缺点是使用外部div来替换highcharts自己的标签函数。

以下是我添加的代码:

首先,一些用于容纳标签和饼图本身的div的CSS样式:

CSS

div#container{
    position:relative;
}
div.outerContainer{
    width:600px;
    height:40px;
    position:absolute;
    top:280px;
    display:none;
    color:white;
    font-family:Helvetica, Arial, Sans;
    font-size:16px;
    font-weight:bold;
    text-transform:uppercase;
}
div.outerContainer > span{
    float:left;
    width:300px;
    text-align:center;
    height:40px;
    line-height:40px;
}

然后,定制load事件代码来计算标签。

        load: function () {
            var cumulativePercentage = 0;
            var $labelTemplate = $("<div class=outerContainer><span class=left></span><span class=right></span></div>");
            $.each(this.series[0].data, function (i, point) {
                $label=$labelTemplate.clone();
                $label.find('span').text(point.name);
                var angle=-90+(cumulativePercentage+point.percentage/2)*360/100;
                if (angle > 90) {
                    angle=angle+180;
                    $label.find('span.right').css({visibility:'hidden'});
                }
                else {
                    $label.find('span.left').css({visibility:'hidden'});
                }
                $label.css({transform:'rotate('+angle+'deg)'});    
                cumulativePercentage+=point.percentage;


                $('#container').append($label);

            });
            $('div.outerContainer').show();
        }

此外,我删除了dataLabels属性。
简要说明: cumulativePercent跟踪每个部分对饼图的贡献程度,以便我们可以将标签精确地插入到每个部分的中心。我们检查角度是否大于90度,以便我们可以:
1. 翻转标签div,使文本不颠倒(如果小于90度,则保留它)。 2. 根据其方向决定文本是在div的左侧还是右侧。
在实际操作中查看它:

  $('#container').highcharts({
        chart: {
            type: 'pie',
            backgroundColor: 'transparent',
            spacing: [0, 0, 0, 0],
            margin: [0, 0, 0, 0],
            events: {
                load: function () {
                    var cumulativePercentage = 0;
                    var $labelTemplate = $("<div class=outerContainer><span class=left></span><span class=right></span></div>");
                    $.each(this.series[0].data, function (i, point) {
                        $label = $labelTemplate.clone();
                        $label.find('span').text(point.name);
                        var angle = -90 + (cumulativePercentage + point.percentage / 2) * 360 / 100;
                        if (angle > 90) {
                            angle = angle + 180;
                            $label.find('span.right').css({visibility: 'hidden'});
                        }
                        else {
                            $label.find('span.left').css({visibility: 'hidden'});
                        }
                        $label.css({transform: 'rotate(' + angle + 'deg)'});
                        cumulativePercentage += point.percentage;


                        $('#container').append($label);

                    });
                    $('div.outerContainer').show();
                }
            }
        },
        title: {
            text: null
        },
        yAxis: {
            title: {
                text: 'Total percent market share'
            }
        },
        plotOptions: {
            pie: {
                borderColor: 'rgb(243, 243, 243)',
                borderWidth: 2,
                shadow: false,
                center: ['50%', '50%'],
                colors: ['rgb(77, 196, 215)', 'rgb(50, 68, 132)', 'rgb(85, 119, 183)']
            }
        },
        tooltip: {
            enabled: false
        },
        series: [{
                type: 'pie',
                name: 'Votes',
                data: [
                    ['Yes', 9],
                    ['No', 5],
                    ['Undecided', 2]
                ],
                size: '90%'
            }]
    });
    div#container{
        position:relative;
    }
    div.outerContainer{
        width:600px;
        height:40px;
        position:absolute;
        top:280px;
        display:none;
        color:white;
        font-family:Helvetica, Arial, Sans;
        font-size:16px;
        font-weight:bold;
        text-transform:uppercase;
    }
    div.outerContainer > span{
        float:left;
        width:300px;
        text-align:center;
        height:40px;
        line-height:40px;
    }
<div id="container" style="height: 600px; width: 600px;"></div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接