Javascript 如何在chart.js中显示每个切片的饼图数据值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33363373/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:59:21  来源:igfitidea点击:

How to display pie chart data values of each slice in chart.js

javascriptphpjquerycharts

提问by Nithya.K

I am using Chart.js for drawing pie chart in my php page.I found tooltip as showing each slice values.
enter image description here

我正在使用 Chart.js 在我的 php 页面中绘制饼图。我发现工具提示显示每个切片值。
在此处输入图片说明

But I wish to display those values like below image. enter image description here

但我希望显示如下图所示的值。 在此处输入图片说明

I do not know how to do this with chart.js.

我不知道如何用 chart.js 做到这一点。

Please help me.

请帮我。

My Javascript code:

我的Javascript代码:

function drawPie(canvasId,data,legend){
    var ctx = $("#pie-canvas-" + canvasId).get(0).getContext("2d");

    var piedata = [];
    $.each(data,function(i,val){
        piedata.push({value:val.count,color:val.color,label:val.status});
    });
    var options =
    {
        tooltipTemplate: "<%= Math.round(circumference / 6.283 * 100) %>%",
    }
    var pie = new Chart(ctx).Pie(piedata,options);
    if(legend)document.getElementById("legend").innerHTML = pie.generateLegend();
}

php code:

php代码:

printf('<table><tr>');
echo '<td style="text-align: right;"><canvas id="pie-canvas-'
    . $canvasId
    . '" width="256" height="256" ></canvas></td><td style="text-align: left;width:360px;height:auto" id="legend" class="chart-legend"></td></tr></table>';

     echo '<script type="text/javascript">drawPie('
    . $canvasId
    . ', '
    . $data3
    .', '
    . $legend
    . ');</script>';

enter image description here

在此处输入图片说明

采纳答案by Spencer Wieczorek

From what I know I don't believe that Chart.JS has any functionality to help for drawing text on a pie chart. But that doesn't mean you can't do it yourself in native JavaScript. I will give you an example on how to do that, below is the code for drawing text for each segment in the pie chart:

据我所知,我不相信 Chart.JS 有任何功能可以帮助在饼图上绘制文本。但这并不意味着您不能在原生 JavaScript 中自行完成。我会给你一个关于如何做到这一点的例子,下面是为饼图中每个段绘制文本的代码:

function drawSegmentValues()
{
    for(var i=0; i<myPieChart.segments.length; i++) 
    {
        // Default properties for text (size is scaled)
        ctx.fillStyle="white";
        var textSize = canvas.width/10;
        ctx.font= textSize+"px Verdana";

        // Get needed variables
        var value = myPieChart.segments[i].value;
        var startAngle = myPieChart.segments[i].startAngle;
        var endAngle = myPieChart.segments[i].endAngle;
        var middleAngle = startAngle + ((endAngle - startAngle)/2);

        // Compute text location
        var posX = (radius/2) * Math.cos(middleAngle) + midX;
        var posY = (radius/2) * Math.sin(middleAngle) + midY;

        // Text offside to middle of text
        var w_offset = ctx.measureText(value).width/2;
        var h_offset = textSize/4;

        ctx.fillText(value, posX - w_offset, posY + h_offset);
    }
}

A Pie Chart has an array of segments stored in PieChart.segments, we can look at the startAngleand endAngleof these segments to determine the angle in between where the text would be middleAngle. Then we would move in that direction by Radius/2to be in the middle point of the chart in radians.

饼图有一个存储在其中的段数组PieChart.segments,我们可以查看这些段的startAngleendAngle以确定文本所在位置之间的角度middleAngle。然后我们将朝那个方向移动,Radius/2以弧度为单位位于图表的中间点。

In the example above some other clean-up operations are done, due to the position of text drawn in fillText()being the top right corner, we need to get some offset values to correct for that. And finally textSizeis determined based on the size of the chart itself, the larger the chart the larger the text.

在上面的例子中,做了一些其他的清理操作,由于在fillText()右上角绘制的文本位置,我们需要得到一些偏移值来纠正它。最后textSize是根据图表本身的大小来确定的,图表越大文字越大。

Fiddle Example

小提琴示例



With some slight modification you can change the discrete number values for a dataset into the percentile numbers in a graph. To do this get the total valueof the items in your dataset, call this totalValue. Then on each segment you can find the percent by doing:

通过稍加修改,您可以将数据集的离散数值更改为图表中的百分位数。为此,获取value数据集中的项目总数,请调用此totalValue。然后在每个段上,您可以通过执行以下操作找到百分比:

Math.round(myPieChart.segments[i].value/totalValue*100)+'%';

The section here myPieChart.segments[i].value/totalValueis what calculates the percent that the segment takes up in the chart. For example if the current segment had a value of 50and the totalValue was 200. Then the percent that the segment took up would be: 50/200 => 0.25. The rest is to make this look nice. 0.25*100 => 25, then we add a %at the end. For whole number percent tiles I rounded to the nearest integer, although can can lead to problems with accuracy. If we need more accuracy you can use .toFixed(n)to save decimal places. For example we could do this to save a single decimal place when needed:

此处的部分用于myPieChart.segments[i].value/totalValue计算该段在图表中所占的百分比。例如,如果当前段的值为50并且 totalValue 为200。那么该段所占的百分比将是:50/200 => 0.25。剩下的就是让这个看起来不错。0.25*100 => 25,然后我们%在最后添加一个。对于整数百分比的瓷砖,我四舍五入到最接近的整数,尽管可能会导致准确性问题。如果我们需要更高的准确性,您可以使用.toFixed(n)来保存小数位。例如,我们可以这样做以在需要时保存一个小数位:

var value = myPieChart.segments[i].value/totalValue*100;
if(Math.round(value) !== value)
    value = (myPieChart.segments[i].value/totalValue*100).toFixed(1);
value = value + '%';

Fiddle Example of percentile with decimals

带小数的百分位数示例

Fiddle Example of percentile with integers

带有整数的百分位数示例

回答by Hung Tran

For Chart.js 2.0and up, the Chart object data has changed. For those who are using Chart.js 2.0+, below is an example of using HTML5 Canvas fillText()method to display data value inside of the pie slice. The code works for doughnut chart, too, with the only difference being type: 'pie'versus type: 'doughnut'when creating the chart.

对于Chart.js 2.0及更高版本,Chart 对象数据已更改。对于那些使用 Chart.js 2.0+ 的人,下面是一个使用 HTML5 CanvasfillText()方法在饼图中显示数据值的示例。该代码也适用于圆环图,唯一的区别是type: 'pie'type: 'doughnut'创建图表时的不同。

Script:

脚本:

Javascript

Javascript

var data = {
    datasets: [{
        data: [
            11,
            16,
            7,
            3,
            14
        ],
        backgroundColor: [
            "#FF6384",
            "#4BC0C0",
            "#FFCE56",
            "#E7E9ED",
            "#36A2EB"
        ],
        label: 'My dataset' // for legend
    }],
    labels: [
        "Red",
        "Green",
        "Yellow",
        "Grey",
        "Blue"
    ]
};

var pieOptions = {
  events: false,
  animation: {
    duration: 500,
    easing: "easeOutQuart",
    onComplete: function () {
      var ctx = this.chart.ctx;
      ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
      ctx.textAlign = 'center';
      ctx.textBaseline = 'bottom';

      this.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 x = mid_radius * Math.cos(mid_angle);
          var y = mid_radius * Math.sin(mid_angle);

          ctx.fillStyle = '#fff';
          if (i == 3){ // Darker text color for lighter background
            ctx.fillStyle = '#444';
          }
          var percent = String(Math.round(dataset.data[i]/total*100)) + "%";      
          //Don't Display If Legend is hide or value is 0
          if(dataset.data[i] != 0 && dataset._meta[0].data[i].hidden != true) {
            ctx.fillText(dataset.data[i], model.x + x, model.y + y);
            // Display percent in another line, line break doesn't work for fillText
            ctx.fillText(percent, model.x + x, model.y + y + 15);
          }
        }
      });               
    }
  }
};

var pieChartCanvas = $("#pieChart");
var pieChart = new Chart(pieChartCanvas, {
  type: 'pie', // or doughnut
  data: data,
  options: pieOptions
});

HTML

HTML

<canvas id="pieChart" width=200 height=200></canvas>

jsFiddle

js小提琴

回答by Kamil Bednarz

I found an excellent Chart.jsplugin that does exactly what you want: https://github.com/emn178/Chart.PieceLabel.js

我找到了一个很好的Chart.js插件,可以完全满足您的需求:https: //github.com/emn178/Chart.PieceLabel.js

回答by JKR

You can make use of PieceLabelplugin for Chart.js.

您可以使用Chart.js 的 PieceLabel插件。

{ pieceLabel: { mode: 'percentage', precision: 2 } }

Demo| Documentation

演示| 文档

The plugin appears to have a new location (and name): DemoDocs.

该插件似乎有一个新位置(和名称): Demo Docs

回答by Srihari Sridharan

@Hung Tran's answer works perfect. As an improvement, I would suggest not showing values that are 0. Say you have 5 elements and 2 of them are 0 and rest of them have values, the solution above will show 0 and 0%. It is better to filter that out with a not equal to 0 check!

@Hung Tran 的回答很完美。作为改进,我建议不要显示 0 的值。假设您有 5 个元素,其中 2 个是 0,其余的都有值,上面的解决方案将显示 0 和 0%。最好用不等于 0 的检查过滤掉它!

          var val = dataset.data[i];
          var percent = String(Math.round(val/total*100)) + "%";

          if(val != 0) {
            ctx.fillText(dataset.data[i], model.x + x, model.y + y);
            // Display percent in another line, line break doesn't work for fillText
            ctx.fillText(percent, model.x + x, model.y + y + 15);
          }
          var val = dataset.data[i];
          var percent = String(Math.round(val/total*100)) + "%";

          if(val != 0) {
            ctx.fillText(dataset.data[i], model.x + x, model.y + y);
            // Display percent in another line, line break doesn't work for fillText
            ctx.fillText(percent, model.x + x, model.y + y + 15);
          }

Updated code below:

更新代码如下:

var data = {
    datasets: [{
        data: [
            11,
            16,
            7,
            3,
            14
        ],
        backgroundColor: [
            "#FF6384",
            "#4BC0C0",
            "#FFCE56",
            "#E7E9ED",
            "#36A2EB"
        ],
        label: 'My dataset' // for legend
    }],
    labels: [
        "Red",
        "Green",
        "Yellow",
        "Grey",
        "Blue"
    ]
};

var pieOptions = {
  events: false,
  animation: {
    duration: 500,
    easing: "easeOutQuart",
    onComplete: function () {
      var ctx = this.chart.ctx;
      ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
      ctx.textAlign = 'center';
      ctx.textBaseline = 'bottom';

      this.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 x = mid_radius * Math.cos(mid_angle);
          var y = mid_radius * Math.sin(mid_angle);

          ctx.fillStyle = '#fff';
          if (i == 3){ // Darker text color for lighter background
            ctx.fillStyle = '#444';
          }

          var val = dataset.data[i];
          var percent = String(Math.round(val/total*100)) + "%";

          if(val != 0) {
            ctx.fillText(dataset.data[i], model.x + x, model.y + y);
            // Display percent in another line, line break doesn't work for fillText
            ctx.fillText(percent, model.x + x, model.y + y + 15);
          }
        }
      });               
    }
  }
};

var pieChartCanvas = $("#pieChart");
var pieChart = new Chart(pieChartCanvas, {
  type: 'pie', // or doughnut
  data: data,
  options: pieOptions
});

回答by Abdul Hameed

Easiest way to do this with Chartjs. Just add below line in options:

使用 Chartjs 最简单的方法。只需在选项中添加以下行:

pieceLabel: {
        fontColor: '#000'
    }

Best of luck

祝你好运