[Chartjs]-How to rotate the Label text in doughnut chart slice vertically in chart.js canvas, Angular 12?

4👍

Using chartjs-plugin-datalabels it can be achieved like this:

options: {
  plugins: {
    datalabels: {
      anchor: "center", //start, center, end
      rotation: function(ctx) {
        const valuesBefore = ctx.dataset.data.slice(0, ctx.dataIndex).reduce((a, b) => a + b, 0);
        const sum = ctx.dataset.data.reduce((a, b) => a + b, 0);
        const rotation = ((valuesBefore + ctx.dataset.data[ctx.dataIndex] /2) /sum *360);
        return rotation < 180 ? rotation-90 : rotation+90;
      },
      formatter: function (value, context) {
          return context.chart.data.labels[context.dataIndex];
      },
    },
  },
}

Resulting piechart

0👍

I also created a video related to your question I saw you also send a message on youtube. Was able to find this Stackoverflow post as your message somehow disappear from Youtube. See explanation regarding to the rotation calculation as it is quite tricky on youtube: https://youtu.be/M251H8RLr3Q

Remember that the rotation option is scriptable so you could make a function out of it to calculate it.

You are close but you need to use the rotation option in the datalabels plugin.

Here are some important items:
The starting point of the angle is 90 degrees, starting from there you can calculate by know the percentage of the slice. You will need to calculate it from the 360 degrees angle. Best is to watch the video to understand deeper explanation.

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
    type: 'doughnut',
    data: {
        labels: ['Big Commerce', 'CRM', 'ZOHO'],
        datasets: [{
            label: 'My First Dataset',
            data: [300, 50, 100], 
            //  == 360 450 (300 / 450) 66 == 120 + 90 // 120 / 3 = 40 / 2 = 20
            // 100 = 80 = 40
            backgroundColor: [
              'rgb(255, 99, 132)',
              'rgb(54, 162, 235)',
              'rgb(255, 205, 86)'
            ],
          datalabels: { 
            rotation: [210, 350, 50]
          }
        },
        {
          label: 'My Second Dataset',
          data: [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
          backgroundColor: [
            'rgb(255, 99, 132)',
            'rgb(255, 99, 132)',
            'rgb(255, 99, 132)',
            'rgb(255, 99, 132)',
            'rgb(255, 99, 132)',
            'rgb(255, 99, 132)',
            'rgb(255, 99, 132)',
            'rgb(255, 99, 132)',
            'rgb(54, 162, 235)',
            'rgb(54, 162, 235)',
            'rgb(255, 205, 86)',
            'rgb(255, 205, 86)'
          ],
          datalabels: {
            // 30 = 360 = 8.33% 
            // 90 = 25% 
            
            // 90 = base
            // 30 / 2 = 15
            // 90 + 15 = 105
            // 90 + 30 + 30
            // 90 + 30 + 15 = 
            rotation: [105, 135, 165, 195, 225, 255, 285, 315, 345, 15, 45, 75]
          }
        }, 
        {
          label: 'My Third Dataset',
          data: [10, 50, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
          backgroundColor: [
            'rgb(255, 99, 132)',
            'rgb(54, 162, 235)',
            'rgb(255, 205, 86)'
          ],
        }]
      },
    plugins: [ChartDataLabels],
    options: {}
});

0👍

In addition, spinning chart and keeping the labels rotated, you can use the solution posted by tomludd and spin the pie with :

let resultValue = 101;
let randomDegree = Math.floor(Math.random() * (355 - 0 + 1) + 0);
let rotationInterval = window.setInterval(() => {
  
  myChart.options.rotation = myChart.options.rotation + resultValue;
  myChart.options.plugins.datalabels.rotation = function(ctx) {
    const valuesBefore = ctx.dataset.data.slice(0, ctx.dataIndex).reduce((a, b) => a + b, 0);
    const sum = ctx.dataset.data.reduce((a, b) => a + b, 0);
    const rotation = myChart.options.rotation + ((valuesBefore + ctx.dataset.data[ctx.dataIndex] /2) /sum *360);
    return rotation-90;
  };
  
  myChart.update();
  
  if (myChart.options.rotation >= 360) {
    count += 1;
    resultValue -= 5;
    myChart.options.rotation = 0;
  } else if (count > 15 && myChart.options.rotation == randomDegree) {
    clearInterval(rotationInterval);
    count = 0;
    resultValue = 101;
  }
}, 25); // timing

You can trigger this on the event you want (button click or whatever you want)

Leave a comment