admin管理员组

文章数量:1410712

How can I add a text label inside Doughnut chart using Chart.js and Angular2? I saw some answers on this topic but none of them are working for me since I am working with Ionic2 app. This is my simplified code:

  import { Chart } from 'chart.js';

    @ViewChild('doughnutCanvas') doughnutCanvas;

    ionViewDidEnter() {

    this.doughnutChart = new Chart(this.doughnutCanvas.nativeElement, {

      type: 'doughnut',
      data: {
        labels: this.titles,
        datasets: [{
          label: '# of Work',
          data: this.times,
          backgroundColor: [
            'rgba(255, 99, 132, 0.5)',
            'rgba(54, 162, 235, 0.5)'
          ],
          hoverBackgroundColor: [
            "#FF6384",
            "#36A2EB"
          ]
        }]
      },
      options: {
        responsive: true,
        legend: {
          display: false
        }
      }
    });
  }

How can I add a text label inside Doughnut chart using Chart.js and Angular2? I saw some answers on this topic but none of them are working for me since I am working with Ionic2 app. This is my simplified code:

  import { Chart } from 'chart.js';

    @ViewChild('doughnutCanvas') doughnutCanvas;

    ionViewDidEnter() {

    this.doughnutChart = new Chart(this.doughnutCanvas.nativeElement, {

      type: 'doughnut',
      data: {
        labels: this.titles,
        datasets: [{
          label: '# of Work',
          data: this.times,
          backgroundColor: [
            'rgba(255, 99, 132, 0.5)',
            'rgba(54, 162, 235, 0.5)'
          ],
          hoverBackgroundColor: [
            "#FF6384",
            "#36A2EB"
          ]
        }]
      },
      options: {
        responsive: true,
        legend: {
          display: false
        }
      }
    });
  }
Share Improve this question edited May 9, 2017 at 7:07 Suraj Rao 29.6k11 gold badges95 silver badges104 bronze badges asked May 9, 2017 at 7:04 user7832762user7832762
Add a ment  | 

3 Answers 3

Reset to default 4

This can be achieved by creating / registering a plugin before generating the chart and you could create the plugin in the following way ...

Chart.plugins.register({
    beforeDraw: function(chart) {
        var data = chart.data.datasets[0].data;
        var sum = data.reduce(function(a, b) {
            return a + b;
        }, 0);
        var width = chart.chart.width,
            height = chart.chart.height,
            ctx = chart.chart.ctx;
        ctx.restore();
        var fontSize = (height / 10).toFixed(2);
        ctx.font = fontSize + "px Arial";
        ctx.textBaseline = "middle";
        var text = sum,
            textX = Math.round((width - ctx.measureText(text).width) / 2),
            textY = height / 2;
        ctx.fillText(text, textX, textY);
        ctx.save();
    }
});

ᴅᴇᴍᴏ

// register plugin
Chart.plugins.register({
    beforeDraw: function(chart) {
        var data = chart.data.datasets[0].data;
        var sum = data.reduce(function(a, b) {
            return a + b;
        }, 0);
        var width = chart.chart.width,
            height = chart.chart.height,
            ctx = chart.chart.ctx;
        ctx.restore();
        var fontSize = (height / 10).toFixed(2);
        ctx.font = fontSize + "px Arial";
        ctx.textBaseline = "middle";
        var text = sum,
            textX = Math.round((width - ctx.measureText(text).width) / 2),
            textY = height / 2;
        ctx.fillText(text, textX, textY);
        ctx.save();
    }
});

// generate chart
var ctx = document.getElementById('canvas').getContext('2d');
var myChart = new Chart(ctx, {
    type: 'doughnut',
    data: {
        labels: ["Red", "Blue", "Yellow"],
        datasets: [{
            data: [300, 50, 100],
            backgroundColor: ["#FF6384", "#36A2EB", "#FFCE56"],
            hoverBackgroundColor: ["#FF6384", "#36A2EB", "#FFCE56"]
        }]
    },
    options: {
        responsive: false,
        legend: {
            display: false
        }
    }
});
<script src="https://cdnjs.cloudflare./ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<canvas id="canvas"></canvas>

If you guys are trying to add legend. You should change the height by using

height = (chart.chartArea.top + chart.chartArea.bottom) / 2
textY = height;

using the chartArea is more correct. Otherwise your text would ignore the height of legend and be located in the wrong place.

For anybody who is using ng2-charts^2.4.2" the registration of the inline plugin can be done via the baseChart directive's input attribute [plugins].

First you have to define a plugins property holding and array of plugins. (You could also register your official plugins there plugins = [ChartDataLabels, {/*inline plugin*/}] )

For correct label placement inside the doughnut chart you have to take into account the position of the legend, which could be above, below or at the left or right side. So I tweaked @GRUNT and @ginagigo123 answers into an ultimate answer that is based on the following calculations

let textX = Math.round(((chart.chartArea.left + chart.chartArea.right) - ctx.measureText(text).width) / 2),
let textY = Math.round((chart.chartArea.top + chart.chartArea.bottom) / 2);
  

poonent.ts


  @ViewChild(BaseChartDirective, { static: true })
  chartNgWrapper: BaseChartDirective;

  plugins = [
    {
      beforeDraw: function (chart: any) {
        let data = chart.data.datasets[0].data;
        let sum = (data as number[]).reduce(function (a, b) {
          return a + b;
        }, 0);
        let width = chart.chartArea.left + chart.chartArea.right,
          height = chart.chartArea.top + chart.chartArea.bottom,
          ctx = chart.chart.ctx;
        ctx.restore();
        let fontSize = (height / 10).toFixed(2);
        ctx.font = fontSize + 'px Arial';
        ctx.textBaseline = 'middle';
        let text = sum,
          textX = Math.round((width - ctx.measureText(text).width) / 2),
          textY = height / 2;
        ctx.fillText(text, textX, textY);
        ctx.save();
      },
    },
  ];

In case you are making an app that can switch language writing mode, you have to get the current rtl (right-to-left) value from somewhere (mine is defined in the legend) and add or substract based on it:

   let textX = chart.legend.options.rtl
       ? Math.round((width + ctx.measureText(text).width) / 2)
       : Math.round((width - ctx.measureText(text).width) / 2),

If you are manipulation the writing direction via an html element's dir attribute (<app-root dir="ltr">) you can also get the current language writing mode from chart.ctx.direction, in this case it returns 'rtl' or 'ltr' strings

ponent.html


<canvas
  baseChart
  #chart
  [datasets]="doughnutChartData"
  [chartType]="doughnutChartType"
  [labels]="doughnutChartLabels"
  [options]="options"
  [plugins]="plugins"
>
</canvas>

本文标签: javascriptText inside Doughnut chart using Chartjs and Angular2Ionic2Stack Overflow