Include Percentage In Legend - chart.js

How would I add the segments percentage to the charts label?
Example
(Percentage values dont reflect the actual chart this is just an example.)
Here's my current template.
<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>

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>

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>

Related

Chartjs and (more compact) title placement

I am using Chartjs for some simple gauges (using pie chart) but when adding the title it is quite far apart and padding doesn't seem to help me :-( Does anyone know a way of placing the title closer to the gauge/pie chart ?
image of title in pie/gauge chart here
var ctx103 = document.getElementById('chart103').getContext('2d');
new Chart(ctx103, {
type: 'doughnut',
data: {
datasets: [{
//label: '# of Votes',
data: [80, 20],
backgroundColor: ["green", "grey"]
}]
},
options: {
rotation: 270, // start angle in degrees
circumference: 180, // sweep angle in degrees
plugins: {
title: {
display: true,
position: 'top',
text: 'TITLE !!!!!',
padding: {
top: 0,
bottom: 0
}
}
}
}
});
I have been trying different padding options but that just moves the title further away ...
While this may not work for your specific application, in some cases this can be achieved using HTML/CSS.
This is the styling I used:
<style>
#titleAndChart {
margin: 0;
position: absolute;
height: 600px;
width: 600px;
box-sizing: border-box;
}
#titleDiv {
position: absolute;
top: 0px;
left: 0px;
width: 600px;
}
#chartDiv {
position: absolute;
top: 60px;
left: 0px;
width: 600px;
}
</style>
The HTML layout then becomes:
<div id="titleAndChart">
<div id="titleDiv">
Chart title goes here
</div>
<div id='chartDiv'>
<canvas id="myChart"></canvas>
</div>
</div>
And the chart itself looks like this:
Chart.defaults.doughnut.circumference = Math.PI;
Chart.defaults.doughnut.rotation = -1 * Math.PI;
new Chart(document.getElementById('myChart'), {
type: 'doughnut',
options: {
legend: {
display: false,
}
},
data: {
labels: ['Red','Green'],
datasets: [{
data: [25,75],
backgroundColor: ['red','green']
}]
}
});
Here's a fiddle using ChartJS v2.9.4:
https://jsfiddle.net/hdahle/4x670et8/
And here's a fiddle using ChartJS v4.0.1
https://jsfiddle.net/hdahle/k8zxvjyq/

Google pie chart vs old flot chart

I have an old pie chart with jquery flot.
And if my series values are:
Apples: 1070
Bananas: 2127
And pie chart looks like
2127 / 1070
Currently, I have google pie chart. And, as i understand, counting happens other way:
(1070 + 2127) / 1070
and
(1070 + 2127) / 2127.
Thus chart looks different.
Is there any way to display values like in an old flot pie?
not sure how the data is being loaded,
but the following two examples look the same to me...
flot
$(document).ready(function() {
var data = [
{label: 'Apples', data: 1070, color: '#e1ab0b'},
{label: 'Bananas', data: 2127, color: '#fe0000'}
];
$.plot($("#chart-flot"), data, {
series: {
pie: {
show: true
}
}
});
});
body, html, .chart {
height: 100%;
margin: 0px;
padding: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.pie.min.js"></script>
<div id="chart-flot" class="chart"></div>
google
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Apples', 1070],
['Bananas', 2127]
]);
var options = {
chartArea: {
height: '100%',
width: '100%',
top: 16,
left: 16,
right: 16,
bottom: 16
},
colors: ['#e1ab0b', '#fe0000'],
height: '100%',
legend: {
position: 'top',
alignment: 'end'
},
width: '100%'
};
var chart = new google.visualization.PieChart(document.getElementById('chart-google'));
chart.draw(data, options);
});
body, html, .chart {
height: 100%;
margin: 0px;
padding: 0px;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart-google" class="chart"></div>

display total in center of donut pie chart using google charts?

I am new to angularjs and google charts i made a pie chart now i want following:
1- display total components inside the centre of the pie charts.
2- display pieSliceText outer side of the pie slice
you can see the
this is what i want:
how can this be done
my sample code:
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1.1','packages':['corechart']}]}"> </script>
<div id="piechart" style="width: 900px; height: 500px;"></div>
javascript:
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Task', 'Hours per Day'],
['Work', 11],
['Eat', 2],
['Commute', 2],
['Watch TV', 2],
['Sleep', 7]
]);
var options = {
height: 360,
width: 360,
pieHole: 0.5,
showLables: 'true',
pieSliceText: 'value',
pieSliceTextStyle: {
color: 'white',
fontSize:18
},
legend: {
position: 'right',
alignment: 'center'
},
chartArea: {
left: 10,
top: 10,
width: '130%',
height: '65%'
},
tooltip: {
trigger:'none'
}
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
OK, try this http://jsfiddle.net/L1tct3Lv/3/ ... its a fast hack but you could certainly vastly improve it by calculating the positions based on sizes and such.
google.setOnLoadCallback(drawChart);
<!-- This generates the google chart -->
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Task', 'Hours per Day'],
['Work', 11],
['Eat', 2],
['Commute', 2],
['Watch TV', 2],
['Sleep', 7]
]);
var options = {
height: 360,
width: 360,
pieHole: 0.8,
showLables: 'true',
pieSliceText: 'value',
pieSliceTextStyle: {
color: 'white',
fontSize:18
},
legend: {
position: 'right',
alignment: 'center'
},
chartArea: {
left: 10,
top: 10,
width: '130%',
height: '65%'
},
tooltip: {
trigger:'none'
}
};
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
jQuery('#cnt').text(data.Gf.length);
chart.draw(data, options);
}
Setting up a few overlays like this:
<div id="JSFiddle">
<div id="chart_div"></div>
<div id="cnt" class="overlay"></div>
<div class="overlay-label">total components</div>
</div>
With this css:
#JSFiddle {
position: relative;
}
.overlay {
display:block;
width:240px;
height:240px;
text-align:center;
vertical-align: middle;
position: absolute;
top: 0px; /* chartArea top */
left: 0px; /* chartArea left */
font-size: 80px;
margin-top: 60px;
}
.overlay-label{
display:block;
width:240px;
height:240px;
text-align:center;
vertical-align: middle;
position: absolute;
top: 0px; /* chartArea top */
left: 0px; /* chartArea left */
margin-top: 140px;
font-size: 20px;
}
Result is this:
Researching about this I found this link: https://codepen.io/cireriddler/pen/yyeLpE
This code isn't my, but I think that he answers the problem splitting the chart from the info inside chart.
Example:
<div id="donutchart" class="col-xs-12 col-sm-6 col-md-4">
<div id="chart"></div>
<div id="labelOverlay">
<p class="used-size">90<span>%</span></p>
<p class="total-size">de economia mensal</p>
</div>
</div>

Merge Jquery Knob Functionality in Chart Js

I am using Doughnut Chart of ChartJS, and here is my code
<!doctype html>
<html>
<head>
<title>Doughnut Chart</title>
<script src="jquery-1.11.3.min.js"></script>
<script src="jquery.knob.js"></script>
<script src="../Chart.js"></script>
<style>
body{
padding: 0;
margin: 0;
}
#canvas-holder{
width:30%;
}
</style>
</head>
<body>
<div id="canvas-holder">
<canvas id="chart-area" width="250" class="knob" height="250"/>
</div>
<script>
var doughnutData = [
{
value: 200,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
},
{
value: 200,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green"
},
{
value: 200,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#4D5360",
highlight: "#616774",
label: "Dark Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
}
];
var options = {
//Boolean - Whether we should show a stroke on each segment
segmentShowStroke : true,
//String - The colour of each segment stroke
segmentStrokeColor : "#fff",
//Number - The width of each segment stroke
segmentStrokeWidth : 0,
//Number - The percentage of the chart that we cut out of the middle
percentageInnerCutout : 80, // This is 0 for Pie charts
//Number - Amount of animation steps
animationSteps : 100,
//String - Animation easing effect
animationEasing : "easeOutBounce",
//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : true,
//Boolean - Whether we animate scaling the Doughnut from the centre
animateScale : false,
showTooltips: false
}
window.onload = function(){
var ctx = document.getElementById("chart-area").getContext("2d");
var myDoughnut = new Chart(ctx).Doughnut(doughnutData, options);
$("#chart-area").click( function(evt){
var activePoints = myDoughnut.getSegmentsAtEvent(evt);
/* do something */
}
);
};
</script>
</body>
</html>
There is a requirement to update the value while clicking on the canvas, in the middle of doughnut chart (Just like in Jquery Knob http://anthonyterrien.com/knob/) i.e the value updates on sliding as well as clicking on the canvas. Is there any way to merge the functionality of these two libraries
It would be better to use that control. That said, you could do it Chart.js too. Here is a fair approximation (note that I've used jQuery for some parts, but you could do the same using plain javascript).
CSS
<style>
.myChartWrapper {
position: relative;
display: inline-block;
}
.myChartValue {
border: none;
font-family: 'Helvetica';
font-size: 20px;
overflow: visible;
width: 2em;
white-space: nowrap;
text-align: center;
position: absolute;
background-color: transparent;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.myChartValue::-ms-clear {
display: none;
}
</style>
HTML
<div class="myChartWrapper">
<canvas id="myChart"></canvas>
<input id="myChartValue" class="myChartValue" />
</div>
Javascript
var value = 20;
var MAX = 200;
var STEP = 1;
var HALFSETCOLOR = "rgba(154, 225, 254, 1)";
var SETCOLOR = "rgba(134, 205, 234, 1)";
var UNSETCOLOR = "rgba(237, 237, 237, 1)";
var data = [];
for (var i = 0; i < MAX; i = i + STEP) {
data.push({
value: STEP,
color: (i < value) ? SETCOLOR : UNSETCOLOR,
label: i
})
}
var canvas = document.getElementById("myChart");
var ctx = canvas.getContext("2d");
var myDoughnutChart = new Chart(ctx).Doughnut(data, {
animation: false,
segmentShowStroke: false,
showTooltips: false
});
$("#myChartValue").val(value);
// half set the sectors
canvas.onmousedown = function (evt) {
var activeSegments = myDoughnutChart.getSegmentsAtEvent(evt);
if (activeSegments.length) {
var value = Number(activeSegments[0].label);
var crossed = false;
myDoughnutChart.segments.forEach(function (segment) {
if (Number(segment.label) >= value)
crossed = true;
if (!crossed && segment.fillColor !== SETCOLOR)
segment.fillColor = HALFSETCOLOR;
else if (crossed && segment.fillColor !== UNSETCOLOR)
segment.fillColor = HALFSETCOLOR;
})
myDoughnutChart.update()
myDoughnutChart.value = value;
$("#myChartValue").val(value);
}
};
canvas.onmousemove = function (evt) {
if (myDoughnutChart.value !== undefined) {
canvas.onmousedown(evt)
}
}
// set / unset sectors
canvas.onmouseup = function () {
var value = myDoughnutChart.value;
if (value !== undefined) {
var crossed = false;
myDoughnutChart.segments.forEach(function (segment, i) {
if (Number(segment.label) >= value)
crossed = true;
if (!crossed)
segment.fillColor = SETCOLOR;
else if (crossed)
segment.fillColor = UNSETCOLOR;
})
myDoughnutChart.value = undefined;
myDoughnutChart.update()
}
};
$("#myChartValue").on("change", function () {
myDoughnutChart.value = Number($("#myChartValue").val());
canvas.onmouseup();
})
It could do with a bit of cleanup (like handling change in direction without lifting the mouse), but comes pretty close to the knob functionality without too much effort.
Fiddle - http://jsfiddle.net/rxrxLo33/

How to apply a label color to a Pie Chart slice from Google Charts API

Hej guys , I tried 2 or 3 different functions but i can´t get any of them to work. I want that the label´s from the 3 different stats are colored in for example white. A picture is below.
var options = {'title':'Lead statistik von<?php echo $_SESSION['user_name'];?>',
'width':400,
'height':300,
backgroundColor:'#0a0a0a',
fontSize:'14',
titleTextStyle: {color:'#FFFFFF'},
slices:
{
0: { color: 'red' },
1: { color: 'purple'},
2: { color: 'blue'}
},
pieSliceTextSlice:{color:'#FFFFFF'}
};
someone got a hint which funtion to use?
Picture :
In order to specify legend text color use legend.textStyle.color property, for example:
var options = {
legend: {
textStyle: { color: 'white' }
}
};
According to Configuration Options:
legend.textStyle
An object that specifies the legend text style. The object has this
format:
{ color: <string>,
fontName: <string>,
fontSize: <number>,
bold: <boolean>,
italic: <boolean> }
The color can be any HTML color string, for example: 'red' or '#00cc00'. Also see fontName and fontSize.
Type: object
Default: {color: 'black', fontName: <global-font-name>, fontSize: <global-font-size>}
Example
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Task', 'Hours per Day'],
['Work', 11],
['Eat', 2],
['Commute', 2],
['Watch TV', 2],
['Sleep', 7]
]);
var options = {
title: 'My Daily Activities',
width: 400,
height: 300,
backgroundColor: '#0a0a0a',
fontSize: '14',
legend: {
textStyle: { color: 'white' }
}
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<div id="piechart" style="width: 900px; height: 500px;"></div>