【问题标题】:Rotating dataLabels in a Highcharts pie chart在 Highcharts 饼图中旋转 dataLabels
【发布时间】:2015-01-31 06:22:18
【问题描述】:

我正在尝试在 Highcharts 饼图的每个部分中旋转和定位 dataLabels,感觉就像我越来越深入,却没有接近解决方案。希望得到一些提示或建议。

说明预期目标的图形:

我的饼图中会有三个部分。我最理想的情况是:

  • 要旋转的每个 dataLabel 基本上为每个段创建一条中心线(由洋红色线说明);和
  • 无论类型大小如何,都要在段中居中的 dataLabel。

关于从哪里开始的建议,或者让我接近的示例?

$(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>

【问题讨论】:

  • 请提供现场演示,并向我们展示您到目前为止所做的工作。
  • 这是我能做的最好的了。 jsfiddle.net/6cn6dtyj你能分享你的进展吗?
  • 添加了一个新代码 sn-p 来分享我迄今为止的工作。

标签: javascript highcharts


【解决方案1】:

Highcharts 不提供饼图中自动旋转数据标签的选项。您可以为 dataLabels 旋转编写自定义函数。

这是一个简单的例子:

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/

类似的话题: Radial Pie Chart Datalabels in 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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-19
      • 1970-01-01
      • 2015-03-15
      • 2012-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多