How to set the percentage on top of the chart using ChartJS?

1

I have the following graphic:

var chartData = [{"visitor": 39, "visit": 1}, {"visitor": 18, "visit": 2}, {"visitor": 9, "visit": 3}, {"visitor": 5, "visit": 4}, {"visitor": 6, "visit": 5}, {"visitor": 5, "visit": 6}]

var visitorData = [],
    visitData = [];

for (var i = 0; i < chartData.length; i++) {
    visitorData.push(chartData[i]['visitor'])
    visitData.push(chartData[i]['visit'])
}

var myChart = new Chart(document.getElementById('mychart'), {
    type: 'doughnut',
    animation:{
        animateScale:true
    },
    data: {
        labels: visitData,
        datasets: [{
            label: 'Visitor',
            data: visitorData,
            backgroundColor: [
                "#a2d6c4",
                "#36A2EB",
                "#3e8787",
                "#579aac",
                "#7dcfe8",
                "#b3dfe7",
            ]
        }]
    },
    options: {
        responsive: true,
        legend: false,
        legendCallback: function(chart) {
            var legendHtml = [];
            legendHtml.push('<ul>');
            var item = chart.data.datasets[0];
            for (var i=0; i < item.data.length; i++) {
                legendHtml.push('<li>');
                legendHtml.push('<span class="chart-legend" style="background-color:' + item.backgroundColor[i] +'"></span>');
                legendHtml.push('<span class="chart-legend-label-text">' + item.data[i] + ' person - '+chart.data.labels[i]+' times</span>');
                legendHtml.push('</li>');
            }

            legendHtml.push('</ul>');
            return legendHtml.join("");
        },
        tooltips: {
             enabled: true,
             mode: 'label',
             callbacks: {
                label: function(tooltipItem, data) {
                    var indice = tooltipItem.index;
                    return data.datasets[0].data[indice] + " person visited " + data.labels[indice] + ' times';
                }
             }
         },
    }
});

$('#my-legend-con').html(myChart.generateLegend());

console.log(document.getElementById('my-legend-con'));
.canvas-con {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 365px;
  position: relative;
}

.canvas-con-inner {
  height: 100%;
}

.canvas-con-inner, .legend-con {
  display: inline-block;
}

.legend-con {
  font-family: Roboto;
  display: inline-block;
}
.legend-con ul {
  list-style: none;
}
.legend-con li {
  display: flex;
  align-items: center;
  margin-bottom: 4px;
}
.legend-con li span {
  display: inline-block;
}
.legend-con li span.chart-legend {
  width: 25px;
  height: 25px;
  margin-right: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js"></script>
<div class="canvas-con">
    <div class="canvas-con-inner">
        <canvas id="mychart" height="250px"></canvas>
    </div>
    <div id="my-legend-con" class="legend-con"></div>
</div>

How do I set percentages on top of each slice of the chart, not just when I hover the mouse pointer, but the information is always there?

EDIT

I solved using the chartjs-plugin-datalabels plugin and this function:

plugins: {
        datalabels: {
            formatter: (value, ctx) => {

                let sum = 0;
                let dataArr = ctx.chart.data.datasets[0].data;
                dataArr.map(data => {
                    sum += data;
                });
                let percentage = (value*100 / sum).toFixed(2)+"%";
                return percentage;


            },
            color: '#fff',
        }
    }
    
asked by anonymous 18.12.2018 / 12:10

1 answer

2

You do not need to change anything in your chart code if you want to show only quantity, just include reference to chartjs- plugin-datalabels.min.js .

But as you need the percentage you need to calculate it as you have identified and resolved. I added your excerpt to the chart to make it easier for anyone who needs the feature.

The snippet that formats and encapsulates the percentage is in the formatter:

var chartData = [{"visitor": 39, "visit": 1}, {"visitor": 18, "visit": 2}, {"visitor": 9, "visit": 3}, {"visitor": 5, "visit": 4}, {"visitor": 6, "visit": 5}, {"visitor": 5, "visit": 6}]

var visitorData = [],
    visitData = [];

for (var i = 0; i < chartData.length; i++) {
    visitorData.push(chartData[i]['visitor'])
    visitData.push(chartData[i]['visit'])
}

var myChart = new Chart(document.getElementById('mychart'), {
    type: 'doughnut',
    animation:{
        animateScale:true
    },
    data: {
        labels: visitData,
        datasets: [{
            label: 'Visitor',
            data: visitorData,
            backgroundColor: [
                "#a2d6c4",
                "#36A2EB",
                "#3e8787",
                "#579aac",
                "#7dcfe8",
                "#b3dfe7",
            ]
        }]
    },
    options: {
        responsive: true,
        legend: false,
        legendCallback: function(chart) {
            var legendHtml = [];
            legendHtml.push('<ul>');
            var item = chart.data.datasets[0];
            for (var i=0; i < item.data.length; i++) {
                legendHtml.push('<li>');
                legendHtml.push('<span class="chart-legend" style="background-color:' + item.backgroundColor[i] +'"></span>');
                legendHtml.push('<span class="chart-legend-label-text">' + item.data[i] + ' person - '+chart.data.labels[i]+' times</span>');
                legendHtml.push('</li>');
            }

            legendHtml.push('</ul>');
            return legendHtml.join("");
        },
        tooltips: {
             enabled: true,
             mode: 'label',
             callbacks: {
                label: function(tooltipItem, data) {
                    var indice = tooltipItem.index;
                    return data.datasets[0].data[indice] + " person visited " + data.labels[indice] + ' times';
                }
             }
         },
         plugins: {
            datalabels: {
               formatter: (value, ctx) => {
                  let sum = 0;
                  let dataArr = ctx.chart.data.datasets[0].data;
                  dataArr.map(data => {
                      sum += data;
                  });
                  let percentage = (value*100 / sum).toFixed(2)+"%";
                  return percentage;
        },
        color: '#fff',
    }
}
    }
});

$('#my-legend-con').html(myChart.generateLegend());

console.log(document.getElementById('my-legend-con'));
.canvas-con {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 365px;
  position: relative;
}

.canvas-con-inner {
  height: 100%;
}

.canvas-con-inner, .legend-con {
  display: inline-block;
}

.legend-con {
  font-family: Roboto;
  display: inline-block;
}
.legend-con ul {
  list-style: none;
}
.legend-con li {
  display: flex;
  align-items: center;
  margin-bottom: 4px;
}
.legend-con li span {
  display: inline-block;
}
.legend-con li span.chart-legend {
  width: 25px;
  height: 25px;
  margin-right: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chartjs-plugin-datalabels.min.js"></script><divclass="canvas-con">
    <div class="canvas-con-inner">
        <canvas id="mychart" height="250px"></canvas>
    </div>
    <div id="my-legend-con" class="legend-con"></div>
</div>
    
18.12.2018 / 12:33