Pauliecode
Pauliecode

Reputation: 127

ChartJS: Percentage labels

First of all, I would like to say that I'm a student learning programming for around a month, so expect to see many mistakes.

I'm working on a website where I use a chart from the ChartJs library. I have one outer circle that shows the hours worked on the company and the hours left to reach the monthly goal. The inner circle shows the days of the month and the days left of the month. Here is the code:

const data = {
    labels: ['Summe', 'Noch um Ziel zu erreichen', 'Tage', 'Verbleibende Tage im Monat'],
    datasets: [
      {
        backgroundColor: ['#5ce1e6', '#2acaea'],
        data: [studenGesamt, (800 - studenGesamt)]
      },
      {
        backgroundColor: ['#cd1076', '#8b0a50'],
        data: [dayD, (23 - dayD)]
      },
  
    ]
  };

// Configuration of the pie chart
let outterChart = new Chart(chart, {
    type: 'pie',
    data: data,
    options: {
    responsive: true,
    plugins: {
      legend: {
        labels: {
          render: 'percentage',
          fontColor: ['green', 'white'],
          precision: 2,
          generateLabels: function(chart) {
            // Get the default label list
            const original = Chart.overrides.pie.plugins.legend.labels.generateLabels;
            const labelsOriginal = original.call(this, chart);

            // Build an array of colors used in the datasets of the chart
            var datasetColors = chart.data.datasets.map(function(e) {
              return e.backgroundColor;
            });
            datasetColors = datasetColors.flat();

            // Modify the color and hide state of each label
            labelsOriginal.forEach(label => {

              // Change the color to match the dataset
              label.fillStyle = datasetColors[label.index];
              
            });

            return labelsOriginal;
          }
        },
        onClick: function(mouseEvent, legendItem, legend) {
          // toggle the visibility of the dataset from what it currently is
          legend.chart.getDatasetMeta(
            legendItem.datasetIndex
          ).hidden = legend.chart.isDatasetVisible(legendItem.datasetIndex);
          legend.chart.update();
        }
      },
       tooltip: {
        callbacks: {
          label: function(context) {
            const labelIndex = (context.datasetIndex * 2) + context.dataIndex;
            return context.chart.data.labels[labelIndex] + ': ' + context.formattedValue;
          }
        }
      },
    }
  },
});

I want to show the percentage of each section of the pie chart on the pie chart. For that I found the plugin "chartjs-plugin-labels", and I added the following link on the script tag so I can use it on my website:

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<script src="script.js"></script>
<script src="https://cdn.jsdelivr.net/gh/emn178/chartjs-plugin-labels/src/chartjs-plugin-labels.js"></script>

On my code, I added the following code (I didn't add the closing brackets here as they are further down in the code and I just wanted to show this small specific part of the code):

plugins: {
      legend: {
        labels: {
          render: 'percentage',
          fontColor: ['green', 'white'],
          precision: 2,

However, this code is not working and no percentages are showing up on the chart. I assume I have done something wrong, maybe on the CDN link or on the code itself, but I can't figure out. If someone could help me, I would really appreciate it! Here is a picture of the chart so you can get an idea of what I exactly want: Chart

Upvotes: 1

Views: 5107

Answers (1)

LeeLenalee
LeeLenalee

Reputation: 31331

The plugin you are trying to use is outdated and doesnt work with chart.js version 3, you can use datalabels plugin.

When using the datalabels plugin you need to use the formatter function to change the values to percentages and you will need to register the plugin:

Chart.register(ChartDataLabels);

const data = {
  labels: ['Summe', 'Noch um Ziel zu erreichen', 'Tage', 'Verbleibende Tage im Monat'],
  datasets: [{
      backgroundColor: ['#5ce1e6', '#2acaea'],
      data: [200, (800 - 200)]
    },
    {
      backgroundColor: ['#cd1076', '#8b0a50'],
      data: [4, (23 - 4)]
    },

  ]
};

var ctx = document.getElementById('chartJSContainer').getContext('2d');

// Configuration of the pie chart
let outterChart = new Chart(ctx, {
  type: 'pie',
  data: data,
  options: {
    responsive: true,
    plugins: {
      datalabels: {
        color: 'white',
        formatter: (val, ctx) => {
          const totalDatasetSum = ctx.chart.data.datasets[ctx.datasetIndex].data.reduce((a, b) => (a + b), 0);
          const percentage = val * 100 / totalDatasetSum;
          const roundedPercentage = Math.round(percentage * 100) / 100
          return `${roundedPercentage}%`
        }
      },
      legend: {
        labels: {
          generateLabels: function(chart) {
            // Get the default label list
            const original = Chart.overrides.pie.plugins.legend.labels.generateLabels;
            const labelsOriginal = original.call(this, chart);

            // Build an array of colors used in the datasets of the chart
            var datasetColors = chart.data.datasets.map(function(e) {
              return e.backgroundColor;
            });
            datasetColors = datasetColors.flat();

            // Modify the color and hide state of each label
            labelsOriginal.forEach(label => {

              // Change the color to match the dataset
              label.fillStyle = datasetColors[label.index];
            });

            return labelsOriginal;
          }
        },
        onClick: function(mouseEvent, legendItem, legend) {
          // toggle the visibility of the dataset from what it currently is
          legend.chart.getDatasetMeta(
            legendItem.datasetIndex
          ).hidden = legend.chart.isDatasetVisible(legendItem.datasetIndex);
          legend.chart.update();
        }
      },
      tooltip: {
        callbacks: {
          label: function(context) {
            const labelIndex = (context.datasetIndex * 2) + context.dataIndex;
            return context.chart.data.labels[labelIndex] + ': ' + context.formattedValue;
          }
        }
      },
    }
  },
});
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.js"></script>
</body>

Upvotes: 4

Related Questions