[Chartjs]-Include Percentage In Legend

5👍

You could update the template to do a couple of extra things. 1 get the total number being represented and then in the loop which displays the label print the result of that labels value as a percentage of the total.

ugly string

 legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% var total = segments.reduce(function(previousValue, currentValue){ return previousValue + currentValue.value;},0); for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%> <%=Math.floor((segments[i].value/total)*100)%>%<%}%></li><%}%></ul>"

broken down

first get the total (here using reduce)

var total = segments.reduce(function(previousValue, currentValue){
    return previousValue + currentValue;
},0);

and then when displaying use the total to work out the percentage (used floor here to just make sure we don’t end up with a horrible number, could even add 0.5 to it before we floor to round to the nearest percent)

Math.floor((segments[i].value/total)*100)

Example (also fiddle)

$(function() {
  var pieChartCanvas = $("#pieChart").get(0).getContext("2d");

  var PieData = [{
    value: 70000,
    color: "#f56954",
    highlight: "#f56954",
    label: "Chrome"
  }, {
    value: 6000,
    color: "#00a65a",
    highlight: "#00a65a",
    label: "IE"
  }, {
    value: 4000,
    color: "#f39c12",
    highlight: "#f39c12",
    label: "FireFox"
  }, {
    value: 4000,
    color: "#00c0ef",
    highlight: "#00c0ef",
    label: "Safari"
  }, {
    value: 3000,
    color: "#3c8dbc",
    highlight: "#3c8dbc",
    label: "Opera"
  }];
  var pieOptions = {
    segmentShowStroke: true,
    segmentStrokeColor: "#fff",
    segmentStrokeWidth: 2,
    percentageInnerCutout: 50,
    animationSteps: 100,
    animationEasing: "easeOutBounce",
    animateRotate: true,
    animateScale: false,
    responsive: true,
    maintainAspectRatio: true,
    legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% var total = segments.reduce(function(previousValue, currentValue){ return previousValue + currentValue.value;},0); for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%> <%=Math.floor((segments[i].value/total)*100)%>%<%}%></li><%}%></ul>"
  };
  var pieChart = new Chart(pieChartCanvas).Doughnut(PieData, pieOptions);

  var helpers = Chart.helpers;
  var legendHolder = document.getElementById('graph-legend');
  legendHolder.innerHTML = pieChart.generateLegend();

  // Include a html legend template after the module doughnut itself
  helpers.each(legendHolder.firstChild.childNodes, function(legendNode, index) {
    helpers.addEvent(legendNode, 'mouseover', function() {
      var activeSegment = pieChart.segments[index];
      activeSegment.save();
      pieChart.showTooltip([activeSegment]);
      activeSegment.restore();
    });
  });
  helpers.addEvent(legendHolder.firstChild, 'mouseout', function() {
    pieChart.draw();
  });

  document.getElementById('graph-legend').appendChild(legendHolder.firstChild);

});
#graph-legend ul {
  list-style: none;
}
#graph-legend ul li {
  display: block;
  padding-left: 30px;
  position: relative;
  margin-bottom: 4px;
  border-radius: 5px;
  padding: 2px 8px 2px 28px;
  font-size: 14px;
  cursor: default;
  -webkit-transition: background-color 200ms ease-in-out;
  -moz-transition: background-color 200ms ease-in-out;
  -o-transition: background-color 200ms ease-in-out;
  transition: background-color 200ms ease-in-out;
}
#graph-legend li span {
  display: block;
  position: absolute;
  left: 0;
  top: 0;
  width: 20px;
  height: 100%;
  border-radius: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.js"></script>
<div class="box-body">
  <canvas id="pieChart" width="787" height="300"></canvas>
</div>
<div id="graph-legend"></div>

0👍

In Chart.js V3 you can use a custom generateLabels function for this:

const options = {
  type: 'pie',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
      label: '# of Votes',
      data: [12, 19, 3, 5, 2, 3],
      backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"]
    }, ]
  },
  options: {
    plugins: {
      legend: {
        labels: {
          generateLabels: function(chart) {
            const data = chart.data;
            if (data.labels.length && data.datasets.length) {
              const {
                labels: {
                  pointStyle
                }
              } = chart.legend.options;

              const max = data.datasets[0].data.reduce((a, b) => (a + b), 0);

              return data.labels.map((label, i) => {
                const meta = chart.getDatasetMeta(0);
                const style = meta.controller.getStyle(i);

                return {
                  text: `${label} (${(data.datasets[0].data[i] * 100 / max).toFixed(2)}%)`,
                  fillStyle: style.backgroundColor,
                  strokeStyle: style.borderColor,
                  lineWidth: style.borderWidth,
                  pointStyle: pointStyle,
                  hidden: !chart.getDataVisibility(i),

                  // Extra data used for toggling the correct item
                  index: i
                };
              });
            }
            return [];
          }
        },
      }
    }
  }
}

const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.js"></script>
</body>

Leave a comment