在Highcharts饼图中旋转dataLabels [英] Rotating dataLabels in a Highcharts pie chart

查看:171
本文介绍了在Highcharts饼图中旋转dataLabels的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Highcharts饼图的每一段中旋转和定位dataLabels,只是觉得我正在让自己更深入,更深入,而没有更接近解决方案。会爱一些提示或建议。



一个图形来说明所需的目标:


我最好喜欢:


  • 每个dataLabel都要旋转,基本上为每个段创建一条中心线(用洋红线表示);和

  • 不管类型大小如何,dataLabel都将位于细分受众群中。


建议在哪里开始这个,或一个样本,让我关闭?

  $(function)(){$('#container')。highcharts({chart:{type:'pie',backgroundColor:'transparent',spacing:[0,0,0,0],margin:[0, 0,0,0],事件:{load:function(){$ .each(this.series [0] .data,function(index,point){var degree =(point.angle * 180)/ Math.PI ; var rotation = 0;(degree <0)&&(degree + = 360); //如果切片位于左半部分,则旋转180 //所以文本不会颠倒如果度数= 90&度数< 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;旋转度= 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 total market share'}},plotOptions:{pie:{borderColor:'rgb(243,243,243)',borderWidth: 2,shadow:false,center:['50%','50%'],颜色:['rgb(77,196,215)','rgb(50,68,132)','rgb(85,系列:[{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 src =http://code.highcharts.com/highcharts.js>< / script>< div id =containerstyle =height:600px; width:100%; >< / div>  

解决方案

我发现旋转标签本身有问题,因为当使用 highcharts 旋转它们时,它似乎将它们围绕自己的轴旋转。要达到最佳效果,您需要旋转关于饼图来源的标签。为了达到这个目的,我直接在饼图上添加了绝对定位的div,并迭代了点来计算基于百分比的旋转。不利的一面是,外部div用于标签,而不是 highcharts 自己的标签功能。



下面是我添加的代码:



首先,包含标签的div的一些CSS样式,和饼图本身:

CSS

  div#container {
position:relative;
}
div.outerContainer {
width:600px;
height:40px;
位置:绝对;
top:280px;
display:none;
颜色:白色;
font-family:Helvetica,Arial,Sans;
font-size:16px;
font-weight:bold;
text-transform:大写;
}
div.outerContainer> span {
float:left;
width:300px;
text-align:center;
height:40px;
line-height:40px;
}

然后,自定义加载事件代码来计算标签

  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 =角度+ 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的左侧还是右侧,具体取决于文本的方向。

    $ b b

     90){角度=角度+ 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; $(#集装箱)追加($标签)。 }); $( div.outerContainer)显示()。 }}},title:{text:null},yAxis:{title:{text:'total total market share'}},plotOptions:{pie:{borderColor:'rgb(243,243,243)',borderWidth: 2,shadow:false,center:['50%','50%'],颜色:['rgb(77,196,215)','rgb(50,68,132)','rgb(85,系列:[{type:'pie',name:'Votes',data:[['Yes',9],['No',5 ],['Undecided',2]],size:'90%'}]});  

      div#container {position:relative; } div.outerContainer {width:600px;高度:40像素;位置:绝对的;顶:280像素;显示:无;白颜色; font-family:Helvetica,Arial,Sans;字体大小:16px的;字体重量:粗体;文本转换:大写; } div.outerContainer> span {float:left;宽度:300像素;文本对齐:中心;高度:40像素;行高:40像素; }  

     < div id =containerstyle = 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>  


    I'm trying to rotate and position the dataLabels in each segment of a Highcharts pie chart and just feel like Im getting myself deeper and deeper without getting closer to a solution. Would love some tips or suggestions.

    A graphic to illustrate the desired goal:

    There will be three segments in my pie chart. I would ideally like:

    • Each dataLabel to be rotated to basically create a center line for each segment (illustrated by the magenta lines); and
    • The dataLabel to be centered in the segment, regardless of type size.

    Suggestions on where to get started with this, or a sample that gets me close?

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

    解决方案

    I found rotating the labels themselves to be problematic, because when using highcharts to rotate them, it seems to rotate them about their own axis. To achieve the best result, you want to rotate the label about the origin of the pie chart. To accomplish this, I appended absolutely positioned divs directly on top of the pie chart, and iterated over the points to calculate the rotation based on percentages. The downside, of course, is that external divs are being used for the labels, rather than highcharts's own labeling functions.

    Here is the code I added:

    First, some CSS styles for the divs which hold the labels, and the pie chart itself:

    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;
    }
    

    Then, custom load event code to calculate the labels

            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();
            }
    

    Also, I deleted the dataLabels property.

    Brief explanation:

    cumulativePercent keeps track of how much of the pie each section contributes, so that we can insert the label exactly in the middle of each section. We check if the angle is greater than 90 degrees so that we can

    1. Flip the label div so that the text is not upside down (or leave it if less than 90 degrees)

    2. Decide if the text should be on the left or right side of the div, depending on its orientation.

    See it in action:

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

    这篇关于在Highcharts饼图中旋转dataLabels的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆