Javascript ChartJS 2.0-饼图上的卷缩标签

Javascript ChartJS 2.0-饼图上的卷缩标签,javascript,charts,html5-canvas,chart.js,Javascript,Charts,Html5 Canvas,Chart.js,我需要用许多值(其中一部分接近)和长值标签绘制图表。数值应显示在图表上(而不是图例)。我正在使用以下插件显示标签: var drawItemsValuesPlugin = { afterDraw: function(chartInstance) { var ctx = chartInstance.chart.ctx; // render the value of the chart above the bar ctx.font = Ch

我需要用许多值(其中一部分接近)和长值标签绘制图表。数值应显示在图表上(而不是图例)。我正在使用以下插件显示标签:

var drawItemsValuesPlugin = {
    afterDraw: function(chartInstance) {

        var ctx = chartInstance.chart.ctx;

        // render the value of the chart above the bar
        ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
        ctx.textAlign    = 'center';
        ctx.textBaseline = 'bottom';        
        ctx.strokeStyle = 'black';
        ctx.font = "bold 11pt Arial";
        ctx.lineWidth = 0.3;

        chartInstance.data.datasets.forEach(function (dataset) {
                for (var i = 0; i < dataset.data.length; i++) {    
                    var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
                        total = dataset._meta[Object.keys(dataset._meta)[0]].total,
                        mid_radius = model.innerRadius + (model.outerRadius - model.innerRadius)/2,
                        start_angle = model.startAngle,
                        end_angle = model.endAngle,
                        mid_angle = start_angle + (end_angle - start_angle)/2;

                    var fact = (chartInstance.config.type == 'pie'?
                        (i%2==0?1:1.6):
                        (i%2==0?0.9:1.1)
                    );
                    var x = mid_radius * fact * Math.cos(mid_angle);
                    var y = mid_radius * fact * Math.sin(mid_angle);

                    ctx.fillStyle = '#fff';

                    var label = chartInstance.config.data.labels[i];
                    var percent = String(Math.round(dataset.data[i]/total*100)) + "%";
                    ctx.fillText(label, model.x + x, model.y + y);
                    ctx.strokeText(label, model.x + x, model.y + y);
                    // Display percent in another line, line break doesn't work for fillText
                    ctx.fillText(dataset.data[i] + ' ('+percent+')', model.x + x, model.y + y + 15);
                    ctx.strokeText(dataset.data[i] + ' ('+percent+')', model.x + x, model.y + y + 15);
                }
            });
    }
};
var drawItemsValuesPlugin={
afterDraw:函数(chartInstance){
var ctx=chartInstance.chart.ctx;
//在条形图上方呈现图表的值
ctx.font=Chart.helpers.fontString(Chart.defaults.global.defaultFontSize,'normal',Chart.defaults.global.defaultFontFamily);
ctx.textAlign='中心';
ctx.textb基线='底部';
ctx.strokeStyle=‘黑色’;
ctx.font=“bold 11pt Arial”;
ctx.lineWidth=0.3;
chartInstance.data.datasets.forEach(函数(数据集){
对于(var i=0;i
但我面临以下问题:

这些值标签是挤成一团的。一个简单的解决方案是将标签放置在图表的轨道上,如下图所示:


如何使用Chart JS 2.0获取此标签位置?

注意:下面的代码无效。只是一个布局

x,y = 0,0 = middle of pie chart / middle of the circle
//这4点=甜甜圈馅饼的一部分

xa[1],ya[1] = x,y point on the outside of circle.
xb[1],yb[1] = x,y point on the outside of circle.
xc[1],yc[1] = x,y point on the inside of circle.
xd[1],yd[1] = x,y point on the inside of circle.
//仅为外圆查找上述坐标的中间

xab[1],yab[1] = x,y point on the outside circle, between xa,ya and xb,yb
//您需要找到以像素为单位的文本高度

function somefunc(){
  //i do know how to do this. 
}
//这是文字高度的一半,所以线条可以画到文字的中点

var label_height_pixel[1] = //no idea how to figure this out
var find_middle_of_text[1] = label_height_pixel[1] / 2;
//制作一个更大的圆,然后添加一点填充,使文本不在圆上

//好的,坏代码,找出x,y坐标。使用

xab[1],yab[1] and x,y
var xtext[1],ytext[1] = outer_circle_radius + find_middle_of_text[1] + padding
在上面的所有内容上运行一个恼人的循环。 更改上面的最后一个代码。所以每次增加一点,它都会增加。因此,没有标签会彼此重叠

my_next_height[2] = outer_circle_radius + label_height_pixel[1] + find_middle_of_text[2] + padding
my_next_height[3] = outer_circle_radius + label_height_pixel[1] + label_height_pixel[2] + find_middle_of_text[3] + padding
my_next_height[4] = outer_circle_radius + label_height_pixel[1] + label_height_pixel[2] + label_height_pixel[3] + find_middle_of_text[3] + padding
您需要在中输入if/then/else函数。检查x是正数还是负数。从我的下一个高度[]向左或向右划一条线

然后把你的课文画进去

还有一点要做的就是从外圆画出一条线,然后到目前为止画出一条线,然后放置标签。但上面代码的切分布局应该给您足够的坐标来实现这一点


我尽量避开x,y和z坐标。如果不翻开小学的旧数学书,我永远记不起数学是如何找到点和角度的。看看你的代码中半径,以及所有的代码,我没有看到我记忆中找到正确的x,y绘图点的普通数学。

如果可以帮助你,试试这个,作为一个简单的解决方案


这是一个初步答案。它的主要目的是给你希望。不可能是最终结果(几天后将是最终结果),因为:

  • 代码是丑陋的,被黑客攻击的,没有文档记录的。它基于您提供的插件
  • 代码需要下一个次要版本的Chart.js2(可能是2.3.1)。我已经建立了Chart.js的主分支,并将其上传到我的Dropbox中,因为需要最近合并的
    layout.padding
    选项,以便在饼图周围为轨道标签提供空间(如果没有此选项,标签将被切断)
  • 肯定需要改进
这是你的电话号码

一条小线将饼图的每个部分连接到轨道中的相应标签。连续标签(除了第一个和最后一个,如果数据集有奇数个元素)将以不同的半径环绕,这样可以避免冲突。但我想需要更多的照顾。主要问题是如何确保图表的响应性<代码>布局。填充是指像素,而不是百分比。此外,标签字体的大小目前是固定的。我认为,只要将标签的位置设置为与画布边框的固定距离(因为填充也是固定的)就可以解决这个问题(调整图表的大小会给出一些想法,但稍后会有更多相关内容)

下面也提供了演示,但它无法从Dropbox加载JavaScript文件(虽然JSFIDLE不应该失败-当更新了Chart.js的CDN版本时,我将更新所有链接):

var drawItemsValuesPlugin={
afterDraw:函数(chartInstance){
var ctx=chartInstance.chart.ctx;
//在条形图上方呈现图表的值
ctx.font=Chart.helpers.fontString(Chart.defaults.global.defaultFontSize,'normal',Chart.defaults.global.defaultFontFamily);
ctx.textAlign='中心';
ctx.textb基线='底部';
ctx.strokeStyle=‘黑色’;
ctx.font=“bold 11pt Arial”;
C
$.plot('#placeholder', data, {
    series: {
        pie: {
            show: true
        }
    },
    legend: {
        show: false
    }
});