How to add text in centre of the doughnut chart using Chart.js?

18,722

Solution 1

It is certainly possible to do something like this in Chart.js v2.x

I think the nicest way to do it is by using a plugin. In fact, Cmyker awnser to the question you linked to even updated his posts to show how this would work in Charts.js v2.x

See his fiddle: https://jsfiddle.net/cmyker/ooxdL2vj/

and the corresponding plugin definition:

Chart.pluginService.register({
  beforeDraw: function(chart) {
    var width = chart.chart.width,
        height = chart.chart.height,
        ctx = chart.chart.ctx;

    ctx.restore();
    var fontSize = (height / 114).toFixed(2);
    ctx.font = fontSize + "em sans-serif";
    ctx.textBaseline = "middle";

    var text = "75%",
        textX = Math.round((width - ctx.measureText(text).width) / 2),
        textY = height / 2;

    ctx.fillText(text, textX, textY);
    ctx.save();
  }
});

Solution 2

You can also add a parameter to the configuration and use this as text:

    "options": {
        title: {
            display: true,
            position: "bottom",
            text: 'Upcoming Meetings'
        },
        legend: {
            display: false
        },
        centertext: "123"
    }

And the javascript would look similar to this (please note: doughnuts have a title but no legend, positioning the centered text was somehow experimenting):

    <script>
        Chart.pluginService.register({
            beforeDraw: function (chart) {
                if (chart.options.centertext) {
                    var width = chart.chart.width,
                            height = chart.chart.height,
                            ctx = chart.chart.ctx;

                    ctx.restore();
                    var fontSize = (height / 80).toFixed(2); // was: 114
                    ctx.font = fontSize + "em sans-serif";
                    ctx.textBaseline = "middle";

                    var text = chart.options.centertext, // "75%",
                            textX = Math.round((width - ctx.measureText(text).width) / 2),
                            textY = height / 2 - (chart.titleBlock.height - 15);

                    ctx.fillText(text, textX, textY);
                    ctx.save();
                }
            }
        });
    </script>

Solution 3

The answer by David works darn well. Thanks. I would like to add that the text is not really centralised as it did not take into account the legend height.

var legendHeight =  chart.legend.height;

textY = height / 2 + legendHeight/2;

Adding these will fix that.

Solution 4

This is for the most up to date version of ChartJs (07/23/2021)

I customized the plugin to work - I couldn't get it to work just by copying and pasting. When I got it to work, dividing by 1.87.

let textY = height / 2 -> let textY = height / 1.87

const centerDoughnutPlugin = {
    id: "annotateDoughnutCenter",
    beforeDraw: (chart) => {
      let width = chart.width;
      let height = chart.height;
      let ctx = chart.ctx;

      ctx.restore();
      let fontSize = (height / 114).toFixed(2);
      ctx.font = fontSize + "em sans-serif";
      ctx.textBaseline = "middle";

      let text = "75%";
      let textX = Math.round((width - ctx.measureText(text).width) / 2);
      let textY = height / 1.87;

      console.log("text x: ", textX);
      console.log("text y: ", textY);

      ctx.fillText(text, textX, textY);
      ctx.save();
    },
  };

  // Register Donut Plugin
  Chart.register(centerDoughnutPlugin);
Share:
18,722
jjose
Author by

jjose

Updated on July 27, 2022

Comments

  • jjose
    jjose almost 2 years

    I want to create a Doughnut graph with two values. Clicking the graphs should print the value in center. I found a solution in stackoverflow similar to my requirement. I would like to use latest Chart.js library from github. Is this feature is available in latest Chart.js?

  • raul
    raul almost 7 years
    Is there a way to change the filltext when I update the chart?
  • Aasim Azam
    Aasim Azam almost 7 years
    Is there a way to change the font family?
  • Munkhdelger Tumenbayar
    Munkhdelger Tumenbayar over 6 years
    Chart.pluginService.register selects all charts how to select specific chart in here
  • Smith
    Smith over 5 years
    To expand on this a bit (incase of multiple charts on one page) var text = $('#'+chart.canvas.id).attr('data-centerval'); and <canvas id="chart-claimed" data-centerval="37.2%"></canvas>
  • Phil
    Phil over 2 years
    this doesn't seem to be working with updating the text
  • Caspar Harmer
    Caspar Harmer about 2 years
    I think the text height thing is caused by this: ctx.textBaseline = "middle";