Chartjs and (more compact) title placement - chart.js

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/

Related

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>

How can I cause a legend to appear to the right of the pie (Chart.JS)?

I'm creating a fairly simple pie chart with Chart.JS like so:
var data = {
labels: [
"Bananas (18%)",
"Lettuce, Romaine (14%)",
"Melons, Watermelon (10%)",
"Pineapple (10%)",
"Berries (10%)",
"Lettuce, Spring Mix (9%)",
"Broccoli (8%)",
"Melons, Honeydew (7%)",
"Grapes (7%)",
"Melons, Cantaloupe (7%)"
],
datasets: [
{
data: [2755, 2256, 1637, 1608, 1603, 1433, 1207, 1076, 1056, 1048],
backgroundColor: [
"#FFE135",
"#3B5323",
"#fc6c85",
"#ffec89",
"#021c3d",
"#3B5323",
"#046b00",
"#cef45a",
"#421C52",
"#FEA620"
]
}
]
};
var optionsPie = {
responsive: true,
scaleBeginAtZero: true,
tooltips: {
callbacks: {
label: function (tooltipItem, data) {
return data.labels[tooltipItem.index] + ": " +
formatter.format(data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]);
}
}
}
};
var ctx = $("#top10ItemsChart").get(0).getContext("2d");
var top10PieChart = new Chart(ctx,
{
type: 'pie',
data: data,
options: optionsPie
});
$("#top10Legend").html(top10PieChart.generateLegend());
It looks decent:
...but I want the pie on the left and the legend on the right, with the legend vertically stacked. How can I accompilish that objective?
UPDATE
I tried this:
CSS
.pieLegend li span {
display: inline-block;
width: 12px;
height: 12px;
margin-right: 5px;
}
HTML
<div id="pie_legend" class="pieLegend"></div>
...as suggested in the accepted answer here, but it makes no difference whatsoever.
UPDATE 2
Fixing the bad ID caused the new legend to display, and adding the "display: false" to the options caused the original one to disappear, but the new one still appears below the pie, crowding outside of its div and bleeding into the quadrant below it (shown hovering over bananas):
UPDATE 3
Here's how it looks with the accepted answer's code applied:
The pie is still puny, but this is much better than it was (and answers the question).
You have to turn the default legend off in the options first with:
legend: {
display: false
},
Also your id selector for your legend was wrong. Fiddle.
Wrap the chart in the <div> and set the height and width of that since the canvas will be responsive to its container, then set the canvas's div and the legend's div as display:inline-block.
HTML
<div id="kpi">
<div id="container">
<canvas id="top10ItemsChart"></canvas>
</div>
<div id="top10Legend" class="pieLegend"></div>
</div>
CSS
#kpi{
height: 400px;
width: 100%;
border: 1px solid black;
background-color: white;
}
.pieLegend li span {
display: inline-block;
width: 12px;
height: 12px;
margin-right: 5px;
}
#top10Legend {
display: inline-block;
}
#container {
display: inline-block;
height: 50%;
width: 50%;
}
#top10Legend>ul{
list-style:none;
}
Another way to right align the legend is to add:
legend: {
position:"right"
}
To the Chart options
JSfiddle

Include Percentage In Legend

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>

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>

How to center-align svg-based Google Charts (since they have position: absolute)

Does anybody please have an idea how to center-align the new (i.e. svg-based) Google Charts?
When I inspect the chart elements at my web page (please scroll down to the jQuery Tabs with several Google Charts at that page), I see that the chart itself is given an absolute position:
<div style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; ">
<svg width="800" height="500" style="overflow: hidden; ">
I'm not sure why Google does it, but it breaks my layout (other than that the charts work well for me):
My CSS-code:
h1,h2,h3,p,div,form {
text-align: center;
}
And I've also tried adding there:
margin-left: auto;
margin-right: auto;
My JavaScript-code:
var money_data;
var money_chart;
var money_options = {
width: 800,
height: 500,
legend: {position: 'top'},
areaOpacity: 1.0,
vAxis: {format: '# $'},
hAxis: {title: 'Номер недели', titleTextStyle: {color: 'blue'}, slantedText: true, viewWindow: {min: 39, max: 52}},
colors: ['CCFFCC', '66CC66', 'FF9999'],
animation: {duration: 1000, easing: 'out'}
};
function initMoney() {
$.ajax({
url: '/money-json.php',
data: { id: 'OK408547485023' },
dataType: 'json'
}).done(function(jsonData) {
money_data = new google.visualization.DataTable(jsonData);
money_chart = new google.visualization.SteppedAreaChart(document.getElementById('money_chart'));
google.visualization.events.addListener(money_chart, 'ready', function() {
$('#money_slider').slider('enable');
});
drawMoney();
});
}
function drawMoney() {
money_chart.draw(money_data, money_options);
}
If no CSS-based solution possible here, could I maybe use JavaScript to move the SVG to the same x-position as the money_slider while enabling the latter (please see the above code)?
You could set the size of money_chart DIV to the size of the graph ( I am guessing 800px ) and use auto margins like this.
#money_chart{
margin-left: auto;
margin-right: auto;
width: 800px;
}
You will need to make the chart side another div here is my code and it works for me
.chart_outside{
position:relative;
display: inline;
border: 2px solid #FFF;
width: 500px;
height: 460px;
background: #000;
margin: 5px 5px 5px 5px;
}
.chart_inside{
position:absolute;
right:0px
;top:0px;
}