ChartJs - width scale of chart area and label area - chart.js

I created a donut chart but its width of data area and label area is not what I intended.
How can I increase the width of data(chart) area - i.e. 60% and decrease the width of label area proportionately?
image link as below
https://i.stack.imgur.com/dsoT3.png
<div style="text-align: center;" class='sector-exposure'>
<canvas
baseChart
[data]="sectorChartData"
[labels]="sectorChartLabels"
[chartType]="exposureChartType"
[options]="exposureChartOptions"
>
</canvas>
</div>
public exposureChartOptions: ChartOptions = {
legend: {
position: right,
labels: {
fontColor: '#d5d6d6',
fontSize: this.isMobileWidth ? 10 : 16,
},
},
};
[1]: https://i.stack.imgur.com/dsoT3.png

May be following settings will work for you. Set responsive to true and maintainAspectRatio to false in the chart options and set style as like as max-height: 300px (more or less); width: auto; in canvas.
...
var config = {
type: 'doughnutLabels',
data: {
...
},
options: {
...
responsive: true, //IMPORTANT
maintainAspectRatio: false, //IMPORTANT
...
legend: {
...
position: 'right',
...
labels: {
...
fontColor: '#d5d6d6',
fontSize: this.isMobileWidth ? 10 : 16,
...
}
},
animation: {
animateScale: true,
animateRotate: true
}
}
};
...

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/

Fix the height of Y-Axis of Bar chart in chart.js?

Requirement: I am working with chart.js. In Bar chart, I want to fix the height of Y-Axis. Is there any attribute or hack to do this?
If you want to control the height of the chart you can change the height of the canvas
<canvas id="statement" height="100px"></canvas>
or if you want to change the height of y-axis values try below. Below will make sure the maximum size of the bar is at 25000,and each step to be at 5000 and the callback will label each as 5k,10k,15k,20k,25k
var chartConfig = {
type: 'bar',
data: data,
options: {
scales: {
yAxes: [{
display: true,
gridLines: {
color: "rgb(210,210,211)"
},
ticks: {
max: 25000,
min: 0,
stepSize: 5000,
beginAtZero: true,
padding: 20,
callback: function(value, index, values) {
return value / 1000 + "k";
}
}
}]
}
}

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>

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/

Google Charts Column width in pixels

I have set the width of my bar chart to 580px. The problem that the chart overflows the area in the view window. Would it be possible to reduce the size of the columns in the chart area to reduce the overall chart size? I mean would it be possible to change the scale for the numbers per pixel for each column so that for example the 280 number is shown in less pixel space?
You can use responsive BarChart.
var options = {
width: "100%", //adjusts according to the screen size
height: 500,
bar: { groupWidth: "75%" },
legend: { position: 'right', textStyle: { color: 'black' } },
isStacked: true,
vAxis: { textStyle: { color: 'black' } },
hAxis: { textStyle: { color: 'black' }, format: ' #,##0.00' },
chartArea: { width: "50%", height: "70%" }};
function resizeCharts() {
// redraw charts, dashboards, etc here
chart.draw(dadosGrafico, options);}
$(window).resize(resizeCharts);