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>
Related
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/
How can i hide the line (in chartjs 2.x) as soon it goes outside the scale boundries?
i came across this question/answer:
How do I hide values past the x-axis in chartjs 2.0?
There they will filter all points outside the scale boundries. But that will only work if you have a point on the min/max, and the curve of the line (if any) will not be correct.
In my situation there isn't always a point for the min and/or max and line is also curved.
I have a situation like this jsfiddle:
https://jsfiddle.net/gyotsv07/1/
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="robots" content="noindex, nofollow">
<meta name="googlebot" content="noindex, nofollow">
<script type="text/javascript" src="/js/lib/dummy.js"></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.2.2/Chart.min.js"></script>
</head>
<body><iframe class="chartjs-hidden-iframe" tabindex="-1" style="width: 100%; display: block; border: 0px; height: 0px; margin: 0px; position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px;"></iframe>
<canvas id="canvas" height="566" style="display: block; width: 849px; height: 566px;" width="849"></canvas>
<script>
var ctx = document.getElementById("canvas").getContext("2d");
/*
var cleanOutPlugin = {
beforeInit: function(chart) {
// Replace `ticks.min` by `time.min` if time-type chart
var min = chart.config.options.scales.xAxes[0].ticks.min;
// Same here with `ticks.max`
var max = chart.config.options.scales.xAxes[0].ticks.max;
var ticks = chart.config.data.labels;
var idxMin = ticks.indexOf(min);
var idxMax = ticks.indexOf(max);
if (idxMin == -1 || idxMax == -1)
return;
var data = chart.config.data.datasets[0].data;
data.splice(idxMax + 1, ticks.length - idxMax);
data.splice(0, idxMin);
ticks.splice(idxMax + 1, ticks.length - idxMax);
ticks.splice(0, idxMin);
}
};
Chart.pluginService.register(cleanOutPlugin);*/
var scatterChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'Scatter Dataset',
data: [{
x: -10,
y: 0
}, {
x: 0,
y: 6
}, {
x: 10,
y: 5
}]
}]
},
options: {
scales: {
xAxes: [{
type: 'linear',
position: 'bottom',
ticks: {
min: -5,
max: 5
}
}]
}
}
});
</script>
</body></html>
is there a solution to prevent drawing outside the scale boundries?
A quick fix to your issue is to remove everything drawn outside of the chart surface.
The following plugin can help you doing it :
Chart.plugins.register({
beforeDatasetsDraw: function(chartInstance) {
var ctx = chartInstance.chart.ctx;
var chartArea = chartInstance.chartArea;
ctx.save();
ctx.beginPath();
ctx.rect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
ctx.clip();
},
afterDatasetsDraw: function(chartInstance) {
chartInstance.chart.ctx.restore();
},
});
Check your updated fiddle here and its result :
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
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>
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>