32

I have found similar questions in Stack Overflow, but all of them were addressed one and two years ago. Now Chart.js has come up in version 2, and lots of the documentation changes. Can someone please help me showing an example of pie chart with labels - or pie chart with all of its segment's tooltips are visible?

UPDATE

Thanks to @potatopeelings, his answer works perfectly for Chart.js v2.1.

Although I initially asked how to permanently show tooltips on pie chart here, I found a better solution: showing values as labels in percentages! It is now enabled for pie chart in Chart.js v2.1. In the chart options:

animation: {
  duration: 0,
  onComplete: function () {
    var self = this,
        chartInstance = this.chart,
        ctx = chartInstance.ctx;

    ctx.font = '18px Arial';
    ctx.textAlign = "center";
    ctx.fillStyle = "#ffffff";

    Chart.helpers.each(self.data.datasets.forEach(function (dataset, datasetIndex) {
        var meta = self.getDatasetMeta(datasetIndex),
            total = 0, //total values to compute fraction
            labelxy = [],
            offset = Math.PI / 2, //start sector from top
            radius,
            centerx,
            centery, 
            lastend = 0; //prev arc's end line: starting with 0

        for (var val of dataset.data) { total += val; } 

        Chart.helpers.each(meta.data.forEach( function (element, index) {
            radius = 0.9 * element._model.outerRadius - element._model.innerRadius;
            centerx = element._model.x;
            centery = element._model.y;
            var thispart = dataset.data[index],
                arcsector = Math.PI * (2 * thispart / total);
            if (element.hasValue() && dataset.data[index] > 0) {
              labelxy.push(lastend + arcsector / 2 + Math.PI + offset);
            }
            else {
              labelxy.push(-1);
            }
            lastend += arcsector;
        }), self)

        var lradius = radius * 3 / 4;
        for (var idx in labelxy) {
          if (labelxy[idx] === -1) continue;
          var langle = labelxy[idx],
              dx = centerx + lradius * Math.cos(langle),
              dy = centery + lradius * Math.sin(langle),
              val = Math.round(dataset.data[idx] / total * 100);
          ctx.fillText(val + '%', dx, dy);
        }

    }), self);
  }
},
Community
  • 1
  • 1
Danny
  • 543
  • 1
  • 5
  • 14
  • I thinks this is what you looking for. http://stackoverflow.com/questions/25661197/chart-js-doughnut-show-tooltips-always/25913101#25913101 – Luke May 03 '16 at 20:18
  • @Luke Hi, thanks for taking your time. Unfortunately that example was using chart.js v1.0.2. The data structures and configurations on v2 are different from v1 – Danny May 03 '16 at 21:27
  • 1
    I would use this one: https://github.com/chartjs/chartjs-plugin-datalabels. This plugin should do what you want. – FranzHuber23 Apr 02 '19 at 08:38

5 Answers5

31

Solution for ChartJs Version > 2.1.5:

Chart.pluginService.register({
  beforeRender: function (chart) {
    if (chart.config.options.showAllTooltips) {
        // create an array of tooltips
        // we can't use the chart tooltip because there is only one tooltip per chart
        chart.pluginTooltips = [];
        chart.config.data.datasets.forEach(function (dataset, i) {
            chart.getDatasetMeta(i).data.forEach(function (sector, j) {
                chart.pluginTooltips.push(new Chart.Tooltip({
                    _chart: chart.chart,
                    _chartInstance: chart,
                    _data: chart.data,
                    _options: chart.options.tooltips,
                    _active: [sector]
                }, chart));
            });
        });

        // turn off normal tooltips
        chart.options.tooltips.enabled = false;
    }
},
  afterDraw: function (chart, easing) {
    if (chart.config.options.showAllTooltips) {
        // we don't want the permanent tooltips to animate, so don't do anything till the animation runs atleast once
        if (!chart.allTooltipsOnce) {
            if (easing !== 1)
                return;
            chart.allTooltipsOnce = true;
        }

        // turn on tooltips
        chart.options.tooltips.enabled = true;
        Chart.helpers.each(chart.pluginTooltips, function (tooltip) {
            tooltip.initialize();
            tooltip.update();
            // we don't actually need this since we are not animating tooltips
            tooltip.pivot();
            tooltip.transition(easing).draw();
        });
        chart.options.tooltips.enabled = false;
    }
  }
});
Fl0R1D3R
  • 862
  • 2
  • 11
  • 22
  • 4
    Thanks! In 2.4.0 it has changed to Chart.plugins.register – Evil Pigeon Nov 21 '16 at 07:37
  • 1
    @Fl0R1D3R - is there any way to make the tooltips "face the other way"? Currently they are facing towards the center, which is an issue for small charts :\ Would appreciate ideas. – st2rseeker Apr 26 '17 at 17:12
  • I would like to add just an improvement that can help others. Adding a check if the number is smaller than 0. if(chart.data.datasets[0].data[j] > 0){ chart.pluginTooltips.push(new Chart.Tooltip({ .... }, chart)); } – Guilherme Felipe Reis Aug 16 '18 at 11:59
  • How would I add an event handler for each tooltip? – Joshua Richards Oct 16 '18 at 16:47
20

With the new Chart.js 2.1 you can write a plugin to do this and control it via an options property


Preview

enter image description here


Script

Note that you need to register the plugin before you initialize the chart

Chart.pluginService.register({
    beforeRender: function (chart) {
        if (chart.config.options.showAllTooltips) {
            // create an array of tooltips
            // we can't use the chart tooltip because there is only one tooltip per chart
            chart.pluginTooltips = [];
            chart.config.data.datasets.forEach(function (dataset, i) {
                chart.getDatasetMeta(i).data.forEach(function (sector, j) {
                    chart.pluginTooltips.push(new Chart.Tooltip({
                        _chart: chart.chart,
                        _chartInstance: chart,
                        _data: chart.data,
                        _options: chart.options,
                        _active: [sector]
                    }, chart));
                });
            });

            // turn off normal tooltips
            chart.options.tooltips.enabled = false;
        }
    },
    afterDraw: function (chart, easing) {
        if (chart.config.options.showAllTooltips) {
            // we don't want the permanent tooltips to animate, so don't do anything till the animation runs atleast once
            if (!chart.allTooltipsOnce) {
                if (easing !== 1)
                    return;
                chart.allTooltipsOnce = true;
            }

            // turn on tooltips
            chart.options.tooltips.enabled = true;
            Chart.helpers.each(chart.pluginTooltips, function (tooltip) {
                tooltip.initialize();
                tooltip.update();
                // we don't actually need this since we are not animating tooltips
                tooltip.pivot();
                tooltip.transition(easing).draw();
            });
            chart.options.tooltips.enabled = false;
        }
    }
});

and then

new Chart(ctx, {
    type: 'pie',
    data: data,
    options: {
        showAllTooltips: true
        ...

With the older 2.x version, you should able to move the same (or similar, I'm not sure about the earlier data structure ) to the options.animation.onComplete


Fiddle - http://jsfiddle.net/q15ta78q/

potatopeelings
  • 40,709
  • 7
  • 95
  • 119
  • All tooltip is not shown when multiple data are with 0 data. link http://jsfiddle.net/q15ta78q/43/ it should show , Red - 0, Green -0, but it is showing only Green-0. How to handle this scenario? There is a open question, if you can answer it would be great. Question: http://stackoverflow.com/questions/37790727/chart-js-donut-doughnut-chart-tooltip-to-be-shown-always-for-all-the-data-all – Raghu Jun 20 '16 at 09:42
  • 6
    I'm using charts.js 2.2.1 and this works if you change `_options : chart.options` to `_options : chart.options.tooltips` - – jessica Aug 21 '16 at 01:42
  • I get the error: Chart.Tooltip.positioners[opts.position] is not a function (version 2.4.0) – LauraNMS Nov 14 '16 at 15:49
  • 1
    @potatopeelings - is there any way to make the tooltips "face the other way"? Currently they are facing towards the center, which is an issue for small charts :\ Would appreciate ideas. – st2rseeker Apr 26 '17 at 17:12
  • @potatopeelings is there a way to do the same with angularchart – Ravi Khambhati Oct 03 '17 at 19:55
15

I was looking for similar solution and came across this chartjs plugin Chart.PieceLabel.js. It has configs to display modes like label, value and percentage.

indusBull
  • 1,834
  • 5
  • 27
  • 39
4

According to the closed issue on the github page for chart.js, displaying tool tips permanently is not recommended.

This comment closing this issue gives more detail:

https://github.com/chartjs/Chart.js/issues/1861#issuecomment-442852768

and this is the recommended plugin for permanent data labels:

https://github.com/chartjs/chartjs-plugin-datalabels

ElllGeeEmm
  • 41
  • 3
0

If you got here because you were looking for a way to make pie charts always look hovered like I was. here is the solution that helped me: https://nobal.in/technology/chart-js/how-to-highlight-selected-in-pie-doughnut/

I just needed a way to programmatically enlarge one part of the pie chart, and this is exactly it

jonyB
  • 9,257
  • 2
  • 8
  • 11