Chart JS not showing all data - chart.js

I am working on the following chart. My plan is to use it to display live data every 1 second with a buffer of 600 points. I want it to display initial data (the entire 600 points) fetches data (simulated through setInterval) then puts it and shift. The problem is that it only displays 12 points.
Question 1: Can you help me what am I missing or is it impossible with ChartJS? Question 2: Is this buffer reasonable with ChartJS?
<!DOCTYPE html>
<html>
<head>
<title>Hello World!!</title>
</head>
<script src="/socket.io/socket.io.js"></script>
<script src="Chart.min.js"></script>
<script>
var socket = io();
socket.on('pv_changed', function(data) { document.getElementById('pv').innerHTML = data.value });
</script>
<style>
</style>
<body>
Hello World!!!<br/>
<label>PV Value: </lable>
<label id="pv">hi</lablel>
<div class="container">
<div>
<canvas id="myChart" height=130px></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['M', 'T', 'W', 'T', 'F', 'S', 'S', 'W', 'T', 'F', 'S', 'S'],
datasets: [{
label: 'Test',
data: Array.apply(null, Array(600)).map(Number.prototype.valueOf,0),
backgroundColor: "rgba(255,153,0,0.4)",
animation: true
}]
},
options: {
responsive: true,
scales: {
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Month'
},
ticks: {
beginAtZero: true,
min: -5,
max: 25,
stepsize: 5
}
}],
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Hello'
},
ticks: {
beginAtZero: true,
min: 0,
max: 600,
stepsize: 50
}
}]
}
}
});
var top = 20;
var now = 0;
setInterval(function() {
myChart.data.datasets[0].data.shift();
myChart.data.datasets[0].data.push(now);
myChart.update();
now = now + 1;
if(now == 20)
now = 0;
}, 1000);
</script>
</div>
</div>
</body>
</html>

It seems that you can't update datasets with myChart.update(). try to create temporary object and then assign that object to myChart.data.datasets. you then need to redraw your chart again. I had the same issue with using chart.js in my angular project link. Did you check link?

Related

Chart.js customize individual vertical axis labels

I am using Chart.js to create a horizontal bar chart as shown below. The y axis has three labels: A, B, C. How do I style those vertical labels individually? For example, I may want to have one or two of those labels bolded and/or red.
I looked at this answer: https://stackoverflow.com/a/65463614/3851085. However, that is a solution for the x-axis. For the y-axis, there needs to be a different solution to compute the x pixel of each label.
The code snippet is with an older version of Chart.js, but I am actually using the latest version.
<html>
<head>
<title>Horizontal Bars</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
</head>
<body>
<div>
<canvas id="canvas" height="100"></canvas>
</div>
<script>
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: ['A', 'B', 'C'],
datasets: [{
data: [[1, 3], [4, 5], [2, 6]],
backgroundColor: 'lightblue'
}]
},
options: {
responsive: true,
legend: {
display: false,
}
}
});
};
</script>
</body>
</html>
The documentation is unclear about that, but you can use arrays in options to configure labels.
Here is your code, refactored to be compatible with Chart.js 4.2.0:
window.onload = function() {
var ctx = document.getElementById('myChart').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'bar',
data: {
labels: ['A', 'B', 'C'],
datasets: [{
data: [[1, 3], [4, 5], [2, 6]],
backgroundColor: 'lightblue'
}]
},
options: {
responsive: true,
indexAxis: 'y',
scales: {
y: {
ticks: {
color: ['#ff0000', '#000000', '#000000'],
font: {
weight: ['bold', 'bold', 'normal']
}
}
}
},
plugins: {
legend: {
display: false
}
}
}
});
};
.chart-container {
position: relative;
height: 90vh;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#4.2.0"></script>
<div class="chart-container">
<canvas id="myChart"></canvas>
</div>

prevent axis label rotation in Chart.js [duplicate]

I'm trying to rotate the title of the y axis 90 degrees clockwise in chart.js but I couldn't find any way to do this.
This question chartjs: trying to rotate the y-Axis label only rotates the ticks/labels not the y axis title itself.
The only related post I can find is this Ability to rotate axis title and the response was from Jan 26, 2021 saying there was no way to do this.
I have attached my javascript and html code below.
Any help would be greatly appreciated.
The y axis title I would like to rotate is highlighted in red and called: Number of defects. Ideally I'd like to rotate it 90 degrees clockwise.
const labels = ['2021-06-07 00:00:00', '2021-06-08 00:00:00', '2021-06-09 00:00:00'];
const data = {
labels: labels,
datasets: [
{
label: 'Fixed defects',
backgroundColor: 'rgb(0, 255, 0)',
borderColor: 'rgb(0, 255, 0)',
data: ['2', '73', '34'],
barThickness: 5
}, {
label: 'Open defects',
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(255, 0, 0)',
data: ['0', '5', '2'],
barThickness: 5
}]
};
const config = {
type: 'bar',
data: data,
options: {
scales: {
x: {
min: '2021-06-07 00:00:00',
max: '2021-09-10 00:00:00',
type: 'time',
time: {
unit: 'week'
},
stacked: true,
title: {
text: 'Dates (weeks)',
display: true
}
},
y: {
stacked: true,
title: {
text: 'Number of defects',
display: true
}
}
}
}
};
const myChart = new Chart(
document.getElementById('myChart'),
config
);
<!DOCTYPE html>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment#^2"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#^1"></script>
<link rel="stylesheet" type="text/css" href="../styles.css">
<body>
<div>
<canvas height="100px" id="myChart"></canvas>
</div>
<script>
</script>
</body>
You can use a custom plugin, to make space you first need to increase the padding on the left, after that you can calculate the correct position by taking the average of the top and bottom y's of the chart area.
Also you should not include chart.js 2 times. When chart.js updates to V4 you will have V4 and V3 installed which will give unwanted behaviour.
Example:
const customTitle = {
id: 'customTitle',
beforeLayout: (chart, args, opts) => {
const {
display,
font
} = opts;
if (!display) {
return;
}
const {
ctx
} = chart;
ctx.font = font || '12px "Helvetica Neue", Helvetica, Arial, sans-serif'
const {
width
} = ctx.measureText(opts.text);
chart.options.layout.padding.left = width * 1.1;
},
afterDraw: (chart, args, opts) => {
const {
font,
text,
color
} = opts;
const {
ctx,
chartArea: {
top,
bottom,
left,
right
}
} = chart;
if (opts.display) {
ctx.fillStyle = color || Chart.defaults.color
ctx.font = font || '12px "Helvetica Neue", Helvetica, Arial, sans-serif'
ctx.fillText(text, 3, (top + bottom) / 2)
}
}
}
const labels = ['2021-06-07 00:00:00', '2021-06-08 00:00:00', '2021-06-09 00:00:00'];
const data = {
labels: labels,
datasets: [{
label: 'Fixed defects',
backgroundColor: 'rgb(0, 255, 0)',
borderColor: 'rgb(0, 255, 0)',
data: ['2', '73', '34'],
barThickness: 5
}, {
label: 'Open defects',
backgroundColor: 'rgb(255, 0, 0)',
borderColor: 'rgb(255, 0, 0)',
data: ['0', '5', '2'],
barThickness: 5
}]
};
const config = {
type: 'bar',
data: data,
options: {
scales: {
x: {
min: '2021-06-07 00:00:00',
max: '2021-09-10 00:00:00',
type: 'time',
time: {
unit: 'week'
},
stacked: true,
},
y: {
stacked: true,
}
},
plugins: {
customTitle: {
display: true,
text: 'Number of defects',
color: 'blue'
}
}
},
plugins: [customTitle]
};
const myChart = new Chart(
document.getElementById('myChart'),
config
);
<!DOCTYPE html>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/chart.js#^3"></script>
<script src="https://cdn.jsdelivr.net/npm/moment#^2"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#^1"></script>
<body>
<div>
<canvas height="100px" id="myChart"></canvas>
</div>
</body>

Datasets in Chart.js stacked barchart appear overlaid instead of stacked

I'm trying to create a stacked barchart using 2 datasets with Chart.js but I find they overlay instead of stack. Is this because of the known bug with a time series for the x-axis or have I done something wrong?
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Chart.js test</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js"></script>
</head>
<body>
<div style="width:90%;margin:20px auto">
<canvas id="myChart" width="90%"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["6 Mar","7 Mar","8 Mar","9 Mar","10 Mar","11 Mar","12 Mar","13 Mar","14 Mar","15 Mar","16 Mar","17 Mar","18 Mar","19 Mar","20 Mar","21 Mar","22 Mar","23 Mar","24 Mar","25 Mar","26 Mar","27 Mar","28 Mar","29 Mar","30 Mar","31 Mar","1 Apr","2 Apr","3 Apr","4 Apr","5 Apr","6 Apr","7 Apr","8 Apr","9 Apr","10 Apr","11 Apr","12 Apr","13 Apr","14 Apr","15 Apr","16 Apr","17 Apr","18 Apr","19 Apr","20 Apr","21 Apr","22 Apr","23 Apr","24 Apr","25 Apr","26 Apr","27 Apr","28 Apr","29 Apr","30 Apr","1 May","2 May","3 May","4 May","5 May","6 May","7 May","8 May","9 May","10 May","11 May","12 May","13 May"],
datasets: [
{
label: 'dataset1',
data: [163,43,67,48,61,74,0,342,342,0,403,407,676,63,1294,1035,665,967,1427,1452,2129,2885,2546,2433,2619,3009,4324,4244,4450,3735,5903,3802,3634,5491,4344,8681,5233,5288,4342,5252,4603,4617,5599,5525,5850,4676,4301,4451,4583,5386,4913,4463,4309,3996,4076,6032,6201,4806,4339,3985,4406,6111,5614,4649,3896,3923,3877,3403,3242],
backgroundColor:'rgb(0,102,204,0.8)'
},{
label: 'dataset2',
data: [1,1,0,1,4,0,2,1,18,15,22,16,34,43,36,56,35,74,149,186,183,284,294,214,374,382,670,652,714,760,644,568,1038,1034,1103,1152,839,686,744,1044,842,1029,935,1115,498,559,1172,837,727,1005,843,420,338,909,795,674,739,621,315,288,693,649,539,626,346,268,210,627,494],
backgroundColor:'rgb(204,0,102,1)'
} ]
},
options: {
layout: {
padding: {
left: 10,
right: 10,
top: 10,
bottom: 10
}
},
legend: {
display: true,
position: 'bottom'
},
scales: {
xAxes: [{
display: true,
stacked: true,
scaleLabel: {
display: true,
labelString: 'Date'
},
ticks: {
autoSkip: true,
maxTicksLimit: 20,
maxRotation: 0,
minRotation: 0,
major: {
fontStyle: 'bold',
fontColor: '#FF0000'
}
}
}],
yAxes: [{
scaleLabel: {
display: true,
stacked: true,
labelString: 'Number'
},
ticks: {
beginAtZero: true
}
}]
},
title: {
display: true,
text: 'Chart title'
},
responsive: true
}
});
</script>
</div>
</body>
</html>
jsfiddle
Hopefully the above jsfiddle explains the issue pictorially. The barchart shows daily data for two datasets which are supposed to be stacked, but dataset1 overlays dataset2 and therefore obscures dataset2 unless transparency is set for dataset1, and then the colour is not correct because it's a combination of one colour over another.
Simply define your yAxes as stacked also as shown below.
yAxes: [{
stacked: true,
Also try to use the latest stable version of Chart.js (currently v2.9.3)
Please have a look at your amended code.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Chart.js test</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
</head>
<body>
<div style="width:90%;margin:20px auto">
<canvas id="myChart" width="90%"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["6 Mar","7 Mar","8 Mar","9 Mar","10 Mar","11 Mar","12 Mar","13 Mar","14 Mar","15 Mar","16 Mar","17 Mar","18 Mar","19 Mar","20 Mar","21 Mar","22 Mar","23 Mar","24 Mar","25 Mar","26 Mar","27 Mar","28 Mar","29 Mar","30 Mar","31 Mar","1 Apr","2 Apr","3 Apr","4 Apr","5 Apr","6 Apr","7 Apr","8 Apr","9 Apr","10 Apr","11 Apr","12 Apr","13 Apr","14 Apr","15 Apr","16 Apr","17 Apr","18 Apr","19 Apr","20 Apr","21 Apr","22 Apr","23 Apr","24 Apr","25 Apr","26 Apr","27 Apr","28 Apr","29 Apr","30 Apr","1 May","2 May","3 May","4 May","5 May","6 May","7 May","8 May","9 May","10 May","11 May","12 May","13 May"],
datasets: [
{
label: 'dataset1',
data: [163,43,67,48,61,74,0,342,342,0,403,407,676,63,1294,1035,665,967,1427,1452,2129,2885,2546,2433,2619,3009,4324,4244,4450,3735,5903,3802,3634,5491,4344,8681,5233,5288,4342,5252,4603,4617,5599,5525,5850,4676,4301,4451,4583,5386,4913,4463,4309,3996,4076,6032,6201,4806,4339,3985,4406,6111,5614,4649,3896,3923,3877,3403,3242],
backgroundColor:'rgb(0,102,204,0.8)'
},{
label: 'dataset2',
data: [1,1,0,1,4,0,2,1,18,15,22,16,34,43,36,56,35,74,149,186,183,284,294,214,374,382,670,652,714,760,644,568,1038,1034,1103,1152,839,686,744,1044,842,1029,935,1115,498,559,1172,837,727,1005,843,420,338,909,795,674,739,621,315,288,693,649,539,626,346,268,210,627,494],
backgroundColor:'rgb(204,0,102,1)'
} ]
},
options: {
layout: {
padding: {
left: 10,
right: 10,
top: 10,
bottom: 10
}
},
legend: {
display: true,
position: 'bottom'
},
scales: {
xAxes: [{
display: true,
stacked: true,
scaleLabel: {
display: true,
labelString: 'Date'
},
ticks: {
autoSkip: true,
maxTicksLimit: 20,
maxRotation: 0,
minRotation: 0,
major: {
fontStyle: 'bold',
fontColor: '#FF0000'
}
}
}],
yAxes: [{
stacked: true,
scaleLabel: {
display: true,
stacked: true,
labelString: 'Number'
},
ticks: {
beginAtZero: true
}
}]
},
title: {
display: true,
text: 'Chart title'
},
responsive: true
}
});
</script>
</div>
</body>
</html>

charts js have a bar spanning negative/positive on y-axis

Is there a way in chartjs to have a bar span across the zero line? As an example,
lets say I have a bar with
data:[x:1, y:100]
How do I tell it to span the y-axis from -100 to 100 (instead of from 0 to 100)?
I have sort of a playground here where I can do either negative or positive per bar, but not both for one bar.
https://jsbin.com/dufonoceja/1/edit?js,output
This can be done since Chart.js v2.9.0, which now supports floating bars. Individual bars can now be specified with the syntax [min, max].
<html>
<head>
<title>Floating Bars</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<style>
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
</style>
</head>
<body>
<div>
<canvas id="canvas" height="120"></canvas>
</div>
<script>
var chartData = {
labels: [1,2,3,4,5,6],
datasets: [{
type: 'bar',
label: 'Red Bar',
borderColor: 'black',
borderWidth: 1,
backgroundColor: 'rgba(128,0,0,0.2)',
data: [[0, 100], [-100, 100], [-30, 40], 0, 0, 0],
}, {
type: 'bar',
label: 'Green Bar',
backgroundColor: 'rgba(0,128,0,0.2)',
borderColor: 'black',
borderWidth: 1,
data: [0, 0, 0, 0, [-50, 70], 100],
}
]
};
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'bar',
data: chartData,
options: {
scaleBeginAtZero: false,
responsive: true,
spanGaps: true,
tooltips: {
mode: 'index',
intersect: true
},
scales: {
xAxes: [{
gridLines: {
display: false
},
}],
yAxes: [{
type: 'linear',
ticks: {
beginAtZero: false,
min:-100,
max:100,
stepSize:30
}
}],
}
}
});
};
</script>
</body>
</html>

Is there a way to put an image into the legend of a bar chart (chart.js)?

A simple stacked bar graph
<head>
<title>Stacked Bar Chart</title>
<script src="Chart.bundle.js"></script>
<script src="utils.js"></script>
<style>
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
</style>
</head>
<body>
<div style="width: 75%">
<canvas id="canvas"></canvas>
</div>
<button id="randomizeData">Randomize Data</button>
<script>
chartColors = {
redborder: 'rgba(206, 0, 23, 1)',
darkredborder: 'rgba(206, 0, 23, 0.75)',
lightredborder: 'rgba(206, 0, 23, 0.5)',
};
var barChartData = {
labels: [1<img src='images/badges/Manchester United.png' alt='Manchester United.png' height='30' width='30'>,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],
datasets: [{
label: 'Goals',
backgroundColor: window.chartColors.redborder,
data: [0,1,3,0,2,0,0,2,0,1,0,1,1,0,0,1,0,0,2,1,0,1,2,1,1,0,0,0,2,2,0,3]
}, {
label: 'Assists',
backgroundColor: window.chartColors.darkredborder,
data: [0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1]
}, {
label: 'Indirect',
backgroundColor: window.chartColors.lightredborder,
data: [0,0,1,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,1,1,0,1,2,0,0,0,1,0,0,0,0,1]
}]
};
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
title: {
display: true,
text: 'Chart.js Bar Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
};
document.getElementById('randomizeData').addEventListener('click', function() {
barChartData.datasets.forEach(function(dataset) {
dataset.data = dataset.data.map(function() {
return randomScalingFactor();
});
});
window.myBar.update();
});
</script>
</body>
</html>
in the x-axis labels, I am trying to get a small icon (image) to be displayed instead of a number. I have tried to put just the image tag in all possible combinations of " and ' as well as with the number. But to no avail. The chart does not render. It seems that the label needs to recognized as a value to render and the html tag knocks this out of place. I don't see why an image tag cannot be put in there, is there a way to do this?