I am using chart.js for my project. As you can see in the following code, chart.js uses different minimum and maximum values for y-axis for line and bar graphs for same data. In the given code, 1100-1700 is the value range for line graph whereas 0-2000 is the value range used for bar graph.
I like to make same minimum and maximum values for both line and bar graphs. One option is to find minimum, maximum and step-size values my own and use the properties min, max and ticks.stepSize under scales. But finding minimum, maximum and step-size for a given data data is a serious task.
For my requirement, default minimum ,maximum and stepSize used by chart.js for line graph is fine and I would like to use the same values for bar graph also.
I could first render line graph, get these values from this graph (like scales.y.min) and then use it for bar graph, which is perfectly working
Is there a way I could get the default min, max, stepSize values used by chart.js for line graph before actually drawing the graph? Any answers or pointers are really appreciated. Thanks
var chart1 = new Chart(document.getElementById('chart1'),
{
type: 'line',
data:
{
labels: ['a','b','c'],
datasets:
[
{
label: 'A',
data: [1212,1122, 1188, 1617, 1116],
borderColor: 'green',
}
]
}
});
var chart2 = new Chart(document.getElementById('chart2'),
{
type: 'bar',
data:
{
labels: ['a','b','c'],
datasets:
[
{
label: 'A',
data: [1212,1122, 1188, 1617, 1116],
backgroundColor: 'green',
}
]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<div style="width:300px;height:200px"><canvas id="chart1"></canvas></div>
<div style="width:300px;height:200px"><canvas id="chart2"></canvas></div>
The first thing you could do is to set beginAtZero to false to Y axis of bar chart because is set to true by default:
https://github.com/chartjs/Chart.js/blob/v3.9.1/src/controllers/controller.bar.js#L636-L650
Then you can set the same scale config to both charts.
options: { // options of charts
scales: {
y: {
beginAtZero: false,
}
}
}
var chart1 = new Chart(document.getElementById('myChart1'),
{
type: 'line',
data:
{
labels: ['a','b','c'],
datasets:
[
{
label: 'A',
data: [1212,1122, 1188, 1617, 1116],
borderColor: 'green',
}
]
},
options: {
scales: {
y: {
beginAtZero: false,
}
}
}
});
var chart2 = new Chart(document.getElementById('myChart2'),
{
type: 'bar',
data:
{
labels: ['a','b','c'],
datasets:
[
{
label: 'A',
data: [1212,1122, 1188, 1617, 1116],
backgroundColor: 'green',
}
]
},
options: {
scales: {
y: {
beginAtZero: false,
}
}
}
});
.myChartDiv {
max-width: 300px;
max-height: 200px;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.9.1/dist/chart.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart1" width="300" height="200"/>
</div>
<div class="myChartDiv">
<canvas id="myChart2" width="300" height="200"/>
</div>
</body>
</html>
Related
We have a new requirement from the business related to chart.js.
Consider the below image where we have bar and line in a single chart. The line chart only has only few points in the chart.
In the application user has the feasiblity to select particular week range which he wantes to get displayed. Suppose if user selected “w16/22” to “w28/22”. As we have one point before “w16/22” i.e. on “w14/22” we need to draw a line chart from y-axis to the first point on the chart i.e. on “w18/22”. Then this is connected to the second point and so on.
Please find the image below for more detailed view of the expected output.
In chart.js is it practically possible to get this output without plotting any value on starting of the y-axis or do we need to approach any other way to get this expected output.
Kindly help me in getting a solution for this issue.
I'm not 100% sure if this works for your specific chart, that said you could simply set the min and max values from the x axes. (For more details here is the link to the documentation).
Like in this example:
/** DEMO TESTDATA START **/
const labels = [
'w01/22', 'w02/22', 'w03/22', 'w04/22',
'w05/22', 'w06/22', 'w07/22', 'w08/22',
'w09/22', 'w10/22', 'w11/22'
];
const clampedLabels = labels.slice(1, labels.length -2)
const dataSet1 = [50, 40, 10, 100, 90 ,60, 20, 10, 100, 90, 90];
const dataSet2 = [... dataSet1]
.map( (n,i) => {
return {y: n, x: labels[i]}
})
.filter((n,i) => i % 2 == 0);
/** DEMO TESTDATA END **/
const data = {
labels: labels,
datasets: [{
label: 'Bar Chart',
data: dataSet1,
backgroundColor: '#0000ff',
order: 1
}, {
label: 'Line Chart',
data: dataSet2,
backgroundColor: '#ff0000',
borderColor: '#ff0000',
type: 'line',
order: 0
}]
};
const config = {
type: 'bar',
data: data,
options: {
responsive: true,
plugins: {
legend: {
position: 'top',
},
title: {
text: 'Unclamped',
display: true
}
}
}
};
const data2 = {
labels: labels,
datasets: [{
label: 'Bar Chart',
data: dataSet1,
backgroundColor: '#0000ff',
order: 1,
fill: false,
}, {
label: 'Line Chart',
data: dataSet2,
backgroundColor: '#ff0000',
borderColor: '#ff0000',
type: 'line',
}]
};
const config2 = {
type: 'bar',
data: data2,
options: {
responsive: true,
plugins: {
legend: {
position: 'top',
},
title: {
text: 'Clamped from W02/22 - W08/22',
display: true,
}
},
scales: {
x: {
min: clampedLabels[0],
max: clampedLabels[clampedLabels.length-2],
}
}
}
};
new Chart( document.getElementById('chart'), config );
new Chart( document.getElementById('chart2'), config2 );
<script src="//cdn.jsdelivr.net/npm/chart.js"></script>
<div class="chart" style="width:500px;">
<canvas id="chart2" ></canvas>
</div>
<div class="chart" style="width:500px;">
<canvas id="chart" ></canvas>
</div>
Your requirement can be achieved by changing the minimum property value of the x-axis. Initially, we have rendered the chart like in the image. We can render the line chart from the start of the y-axis by setting the minimum value of the x-axis based on your requirement. We have created a simple angular application to demonstrate the same. Please find the below stackblitz link for your reference.
Sample link: https://stackblitz.com/edit/angular-a3xvsv-2iblmd?file=app.component.ts
Code Snippet:
<button (click)="changeMinValue($event)">Change value</button>
<ejs-chart style='display:block;' #chart [chartArea]='chartArea' [width]='width' align='center' id='chartcontainer' [primaryXAxis]='primaryXAxis' [primaryYAxis]='primaryYAxis' [zoomSettings]='zoom'
[tooltip]='tooltip' (load)='load($event)'>
<e-series-collection>
<e-series [dataSource]='data' fill="red" type='StackingColumn' xName='x' yName='y' width=2> </e-series>
<e-series [dataSource]='data' fill="yellow" type='StackingColumn' xName='x' yName='y1' width=2 > </e-series>
<e-series [dataSource]='data' fill="blue" type='StackingColumn' xName='x' yName='y2' width=2 > </e-series>
<e-series [dataSource]='data' fill="green" type='StackingColumn' xName='x' yName='y3' width=2 > </e-series>
<e-series [dataSource]='data1' fill="red" type='Line' xName='x' yName='y' width=3 [marker]='marker'> </e-series>
</e-series-collection>
</ejs-chart>
public changeMinValue(e: Event): void {
this.chart.primaryXAxis.minimum = 3;
this.chart.refresh();
}
Screenshot:
Initial rendering:
After clicking on the button:
I have been struggling to make a chart.js line chart start at 0 when all of the values are 0. If all of the data of a dataset is 0 the y axis will always show values below 0 which I don't want there.
Here is the example:
<div class="container">
<canvas id="lineChart"></canvas>
<script>
var ctx = document.getElementById('lineChart');
var lineChart = new Chart(ctx, {
type: 'line',
data: {
labels: [1,2,3],
datasets: [{
data: [0, 0, 0]
}]
},
options: {
responsive: true,
scales: {
y: {
ticks: {
beginAtZero:true
}
}
}
}
});
</script>
<div>
As you can see I am changing the options the scales as suggested in the documentation here (apparently there has been migration and this is the way to go in v3, which is what I am using). But the graph still won't start at 0:
Any axis options other than the ticks work correctly.
Any ideas of what I might be doing wrong?
You tried to place the beginAtZero in the V2 place, in V3 you have to put it in the root of the scale object like so:
const options = {
type: 'line',
data: {
labels: [1, 2, 3],
datasets: [{
label: '# of Votes',
data: [0, 0, 0],
borderColor: 'pink'
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
}
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>
For all changes between V2 and V3 you can read the migration guide
The Chart Spans across the entire Web Page and I cant resize it. I've tried seting the height/width of the canvas and the canvas with no luck.
Here is my Html:
<div id="chartbox">
<canvas id="myChart" display="block"></canvas>
</div>
<script>
var xaxis = [1,2,3,4,5]
var yaxis = [2,3,4,5,6]
var thisChart = new Chart(document.getElementById("myChart"), {
type: 'line',
options: {
responsive: true
},
data: {
labels: xaxis,
datasets: [
{
data: yaxis,
label: "Test",
borderColor: "#3e95cd",
}
]
}
});
</script>
If you are styling the canvas element directly with non relative values you need to set responsive to false in the options, if you are styling the width with relative values you need to apply them to the surrounding div
https://www.chartjs.org/docs/master/configuration/responsive.html
I hope my answer is helpful to you, you just have to specify certain CSS rules for the parent element of the graphic.
var xaxis = [1,2,3,4,5]
var yaxis = [2,3,4,5,6]
var thisChart = new Chart(document.getElementById("myChart"), {
type: 'line',
options: {
responsive: true
},
data: {
labels: xaxis,
datasets: [
{
data: yaxis,
label: "Test",
borderColor: "#3e95cd",
}
]
}
});
#chartbox {
display: block;
width: 400px;
height: 400px;
}
<div id="chartbox">
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
I have a bar chart using Chartjs, with a fixed y-axis max. Sometimes the data can exceed the max, but the hover tooltip is always anchored to the top of the bars so it cannot be seen. The tooltips' position option does not really work for me.
So, is there a way to display the tooltip at the bottom of the bars? Or can it follow the hovering mouse cursor like canvasjs?
var ctx = document.getElementById("chart").getContext("2d");
var barChart = new Chart(ctx, {
type: 'bar',
options: {
scales: {
yAxes: [{
display: true,
ticks: {
min: 0,
max: 120
},
}],
},
tooltips: {
// position: 'nearest',
position: 'average',
},
legend: {
display: false
}
},
data: {
labels: ["A", "B", "C", "D"],
datasets: [{
label: "Data Set 1",
backgroundColor: [
'#44b2d7',
'#44b2d7',
'#44b2d7',
'#44b2d7',
],
borderColor: [
'#44b2d7',
'#44b2d7',
'#44b2d7',
'#44b2d7'
],
borderWidth: 0,
data: [131, 65, 165, 85]
}]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<canvas id="chart" height="180"></canvas>
New modes can be defined by adding functions to the Chart.Tooltip.positioners map.
You can create your custom postitioning like in the Doc of chartjs:
Chart.Tooltip.positioners.custom = function(elements, eventPosition) {
/** #type {Chart.Tooltip} */
var tooltip = this;
/* ... */
return {
x: eventPosition.x,
y: eventPosition.y
};
}
you need to set your custom function into your options when rendering your chart:
tooltips: {
position : 'custom', //<-- important same name as your function above
callbacks: {
label: function(tooltipItem, data) {
var label = Math.floor(tooltipItem.yLabel*100)/100+" "+data.datasets[tooltipItem.datasetIndex].label;
return label;
}
}
}
Look my full Fiddle example.
Just wondering if there is any way to set the horizontal bar labels for y-axis using chart.js. Here is how I set up the chart:
<div class="box-body">
<canvas id="chart" style="position: relative; height: 300px;"></canvas>
</div>
Javascript:
var ctx = document.getElementById('chart').getContext("2d");
var options = {
layout: {
padding: {
top: 5,
}
},
responsive: true,
animation: {
animateScale: true,
animateRotate: true
},
};
var opt = {
type: "horizontalBar",
data: {
labels: label,
datasets: [{
data: price,
}]
},
options: options
};
if (chart) chart.destroy();
chart= new Chart(ctx, opt);
chart.update();
As you all can see, the first and third labels are too long and cut off. Is there a way to make the label multi-line?
If you want to have full control over how long labels are broken down across lines you can specify the breaking point by providing labels in a nested array. For example:
var chart = new Chart(ctx, {
...
data: {
labels: [["Label1 Line1:","Label1 Line2"],["Label2 Line1","Label2 Line2"]],
datasets: [{
...
});
You can use the following chart plugin :
plugins: [{
beforeInit: function(chart) {
chart.data.labels.forEach(function(e, i, a) {
if (/\n/.test(e)) {
a[i] = e.split(/\n/);
}
});
}
}]
add this followed by your chart options
ᴜꜱᴀɢᴇ :
add a new line character (\n) to your label, wherever you wish to add a line break.
ᴅᴇᴍᴏ
var chart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: ['Jan\n2017', 'Feb', 'Mar', 'Apr'],
datasets: [{
label: 'BAR',
data: [1, 2, 3, 4],
backgroundColor: 'rgba(0, 119, 290, 0.7)'
}]
},
options: {
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
}
},
plugins: [{
beforeInit: function(chart) {
chart.data.labels.forEach(function(e, i, a) {
if (/\n/.test(e)) {
a[i] = e.split(/\n/);
}
});
}
}]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="ctx"></canvas>