How to fix the percentage on top of the chart using Chartjs?

Asked

Viewed 1,258 times

1

I have the following chart:

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>
<script src="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 fix the percentages on top of each slice of the graph, not just when I pass the mouse pointer, but that the information is always there?

EDIT

I solved using the plugin chartjs-plugin-datalabels and that 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',
        }
    }
  • 1

    uses Amcharts he already has it

  • 1

    https://www.amcharts.com/demos/#pie

  • Man na doc has a property option that you choose where and if you want it to appear.. gives a little peek insert link description here

  • 1

    Rafael, I hope you don’t mind but I transported the section you calculated the percentage and formatted to facilitate for those who have this doubt. :)

1 answer

3


You don’t 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 since you need the percentage, it is necessary to calculate it as you identified and solved it. I added your snippet to the chart to make it easier for those who need the resource.

The chunk that caculates and formats the percentage is in the parameter formwork:

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>
<script src="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>

<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>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.