I'm trying to create a chart.js scatter plot with a set of points with values of 0 to 100 percent. I'd like to have 0 be a red point and 100 be blue and have a gradient between the two. I'm able to get the colors I want, but is it possible to get labels for just a few points like 0, 25, 50, 75, and 100? I don't want a label for all 101 possible values just enough for users to understand that it's a spectrum.
I considered trying to add two datasets to the chart one for the real data with no labels and another with not data but the five labels I want. Would this work?
Yes, you can specify the ticks you want with the afterBuildTicks hook. You can also specify the count property in the ticks this will make it so chart.js generates that many ticks but you dont have control over the values of those ticks:
const data = [];
for (let i = 0; i < 100; i++) {
data.push({
x: i,
y: i
})
}
const options = {
type: 'scatter',
data: {
datasets: [{
label: '# of Votes',
data: data,
borderColor: 'orange',
backgroundColor: 'orange'
}]
},
options: {
scales: {
x: {
afterBuildTicks: (a) => (a.ticks = [{
value: 0
}, {
value: 25
}, {
value: 50
}, {
value: 75
}, {
value: 100
}]),
ticks: {
count: 5, // limit to 4 ticks but let chart.js decide what tose ticks are
}
}
}
}
}
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.1/chart.js"></script>
</body>
so I'm basically pulling my hair as I can't get this to work for hours straight.
I'm trying to do a (I assumed simple) line-graph with on the x-axis time of day in hours and on the y-axis number of views. I'm trying to set the x-axis range as -24 hours until now.
My code is as follows. What am I doing wrong?
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js"></script>
<div style="width: 500px; height: 500px;"><canvas id="myChart" width="400" height="400"></canvas></div>
<script>
var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: '# of Votes',
data: [{x:'1619701200',y:41},{x:'1619704800',y:9},{x:'1619708400',y:21}]
}]
},
options: {
scales: {
x: {
type: 'time',
min: Date.now() - (24 * 60 * 60 * 1000),
max: Date.now()
}
}
}
});
</script>
EDIT: the problem is that the x-axis doesn't extend to 24 hours prior to now(). Also, there are 3 values in the dataset, but only two are shown. You can even edit the x-values to whatever you want and the entire graph stays the same.
EDIT2:
Could someone help me get this right? I've pasted my data below:
What I am trying to achieve:
X-axis going from now until 24 hours prior with an interval of 1 hour between ticks, formatted as 'd-m-Y H:00:00'. The data now is in seconds since epoch, if I need to change that please let me know!
Y-axis going from 0 to whatever the max is in the dataset
What CDNs do I have to include? I find the documentation on chart.js, moments, adapters etc quite unclear and everything I find on the internet is for prior versions.
Thank you!!
<div style="width: 500px; height: 500px;"><canvas id="myChart" width="400" height="400"></canvas></div>
<script>
new Chart(document.getElementById("myChart"), {
type: 'line',
data: {
labels: ['1619701200','1619704800','1619708400','1619715600','1619719200','1619722800','1619726400','1619730000','1619733600','1619737200','1619744400','1619773200','1619780400','1619784000','1619787600','1619791200','1619794800','1619798400','1619802000','1619809200','1619812800','1619816400','1619820000','1619823600','1619856000'],
datasets: [{
data: [41,9,21,80,277,151,68,88,82,48,12,1,97,36,81,21,63,49,44,15,10,44,81,4,9],
label: "Views",
borderColor: "#3e95cd",
fill: false
},
{
data: [1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,4,1,1],
label: "Visitors",
borderColor: "#3e95cd",
fill: false
}
]
}
</script>
We want you to keep your hair :-)
Try the following 2 Options for latest version of Chart.js
Chart.js v3.2.1 (not backwards compatible with v2.xx)
Option 1:
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
// gets you the latest version of Chart.js, now at v3.2.1
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment"></script>
// You need moment.js and adapter for time or timeseries to work at x-Axis
<div style="width: 500px; height: 500px">
<canvas id="myChart" width="400" height="400"></canvas>
</div>
<script>
const startDate = new Date(1619701200*1000);
// first label from your data, times 1000 to get milliseconds,
// for last 24 hours from now, see further down below
const myLabels = [];
let nextHour = startDate;
let i = 0; // tip: declare i outside for-loop for better performance
for (i; i < 24; i++) {
nextHour = new Date((1619701200 + (i*3600)) *1000);
myLabels.push(nextHour);
};
const ctx = document.querySelector('canvas').getContext('2d');
const myChart3x = new Chart(ctx, {
type: 'line',
data: {
labels: myLabels,
datasets: [{
data: [41,9,21,80,277,151,68,88,82,48,12,1,97,36,81,21,63,49,44,15,10,44,81,4,9],
label: "Views",
borderColor: "#3e95cd",
fill: false
},
{
data: [1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,4,1,1],
label: "Visitors",
borderColor: "#3e95cd",
fill: false
}
]
},
options: {
scales: {
x: {
type: 'timeseries',
time: {
unit: 'hour', // <-- that does the trick here
displayFormats: {
hour: 'D-M-Y H:00:00'
},
tooltipFormat: 'D-M-Y H:00:00' // <-- same format for tooltip
}
},
y: {
min: 0
}
}
}
});
</script>
And this is what your chart would look like:
If you want to calculate dynamically the last 24 hours from now for your x-Axis, I would suggest to use moment.js instead:
<script>
// ...
const startDate = moment().subtract(1, 'd');
const myLabels = [];
let nextHour = startDate;
let i = 0;
for (i; i < 24; i++) {
nextHour = moment().add(i, 'h');
myLabels.push(nextHour);
};
// ....
</script>
Also, be aware that moment.js uses slightly different formatting string:
'D-M-Y H:00:00' instead of 'd-m-Y H:00:00'
Option 2:
If you have your data in json-format
data: [{x:1620237600000,y:41},{x:1620241200000,y:9},{x:1620244800000,y:21}]
like your first code snippet on top, using min and max at x-Axis: (Advantage: you don't have to define labels-array for x-Axis)
<script>
const ctx = document.querySelector("canvas").getContext("2d");
var myChart = new Chart(ctx, {
type: "line",
data: {
datasets: [{
label: "Views",
data: [{x:1620237600000,y:41},{x:1620241200000,y:9},{x:1620244800000,y:21}]
// x-value without quotes (has to be a number)
// and multiply by 1000 to get milliseconds
},
{
label: "Visitors",
data: [{x:1620237600000,y:1},{x:1620241200000,y:1},{x:1620244800000,y:2}]
}]
},
options: {
scales: {
x: {
type: "time", // <-- "time" instead of "timeseries"
min: Date.now() - (24 * 60 * 60 * 1000),
max: Date.now(),
time: {
unit: "hour", // <-- that does the trick here
displayFormats: {
hour: "D-M-Y H:00:00"
},
tooltipFormat: "D-M-Y H:00:00"// <-- same format for tooltip
}
},
y: {
min: 0,
max: 100
}
}
}
});
</script>
You should get the following:
I hope I understood correctly your need and hope this helps.
It needs more settings, I've searched and by trial/error - credit to this jsfiddle - , these are the results.
See updated working jsfiddle:
/*
Source: https://jsfiddle.net/microMerlin/3wfoL7jc/
*/
var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: '# of Votes',
data: [{
x: '1619701200',
y: 41
}, {
x: '1619704800',
y: 9
}, {
x: '1619708400',
y: 21
}]
}]
},
options: {
responsive: true,
scales: {
xAxes: [{
min: Date.now() - (24 * 60 * 60 * 1000),
max: Date.now(),
type: "linear",
position: "bottom",
//stacked: true,
ticks: {
//beginAtZero: true,
userCallback: function(t, i) {
/*console.log("t: " + t.toString());
console.log("i: " + i.toString());*/
return i;
}
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="width: 500px; height: 500px;"><canvas id="myChart" width="400" height="400"></canvas></div>
I have a ChartJS v2 bubble chart with multiple datasets where I want to represent certain data points with different shaped elements.
I've read about point configuration options for pointStyle so the element points can be different shapes, other than circles.
I've tried a few variations and places to add pointStyle but I can't get it working. I only ever see circles.
Is this even possible with a bubble chart?
If not is it possible with a scatter chart?
If anyone still needs to know this. You can put it in the dataset itself to apply only to that dataset, in options.datasets.bubble to make it apply to all bubble datasets, in options.elements.point to apply it to all point elements or in the root of the options to apply it to the whole chart:
const image = new Image()
image.src = 'https://www.chartjs.org/docs/master/favicon.ico';
const options = {
type: 'bubble',
data: {
datasets: [{
label: '# of Votes',
data: [{
x: 20,
y: 30,
r: 15
}, {
x: 40,
y: 10,
r: 10
},
{
x: 30,
y: 22,
r: 25
}
],
pointStyle: (ctx) => (ctx.dataIndex === 2 ? image : 'rectRot'),
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)'
}]
},
options: {
pointStyle: (ctx) => (ctx.dataIndex === 2 ? image : 'rectRot'),
elements: {
point: {
pointStyle: (ctx) => (ctx.dataIndex === 2 ? image : 'rectRot')
}
},
datasets: {
bubble: {
pointStyle: (ctx) => (ctx.dataIndex === 2 ? image : 'rectRot')
}
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
image.onload = () => new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.js"></script>
</body>
To the pointStyle you can pass either a canvas element, image or one of the following strings:
'circle'
'cross'
'crossRot'
'dash'
'line'
'rect'
'rectRounded'
'rectRot'
'star'
'triangle'
Using Chart.js, I'm trying to get the x-axis (and toolips) to show a DATE, but all I can get are large integers appearing as the x-axis label. I've compared what the example in the documentation does and I don't see what it's doing that i'm not. Can anyone please help?
Here's the tiny example that I created showing it not working.
(btw - as a side issue, notice that if the color of the RED line is spelled Red rather than red, the line looks normal, but tooltips no longer work on that line)
https://plnkr.co/edit/CKUf4zFC1vhe3VNUF5Lf?p=preview
javascript for the above plunker example is below
----------------------------------------------------
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div>
<canvas id="canvas"></canvas>
<script>
var chartData = {
datasets: [{
borderColor: 'Red',
label: 'Capital R in borderColor, tooltips dont work',
data: [{
x: new Date('2011-04-11T11:45:00'),
y: 25
}, {
x: new Date('2011-04-11T12:51:00'),
y: 28
}, {
x: new Date('2011-04-11T14:10:00'),
y: 22
}, {
x: new Date('2011-04-11T15:15:00'),
y: 18
}]
}, {
borderColor: 'green',
label: 'borderColor all lower case, tooltips now work',
data: [{
x: new Date('2011-04-11T11:45:00'),
y: 15
}, {
x: new Date('2011-04-11T12:51:00'),
y: 18
}, {
x: new Date('2011-04-11T14:10:00'),
y: 12
}, {
x: new Date('2011-04-11T15:15:00'),
y: 8
}]
}, ]
};
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
window.myScatterxx = Chart.Scatter(ctx, {
data: chartData,
scaleType: 'date',
options: { title: { display: true, text: "scaleType='date' isn't working", fontSize:36} },
});
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.2.1/Chart.min.js">
</script>
</body>
</html>
First of all, since the documentation is messy, I'm not surprised you didn't get how to create a time-scale chart. The actual call is the following :
window.myScatterxx = Chart.Scatter(ctx, {
data: chartData,
options: {
title: {
display: true,
text: "it is now working",
fontSize: 36
},
scales: {
xAxes: [{
// This is the important part
type: "time",
}]
}
},
});
Now you have the correct syntax, you'd need to import the correct library as well. As I can see in the piece of code you gave, you imported Chart.min.js, but you need more since you know work with the time element.
You can either :
Import Moment.js (CDN link) and then Chart.min.js.
Import Chart.bundle.min.js, that contains both Moment and Chart libraries.
Finally, I also noticed in your code you had a problem displaying tooltips for the red dataset. It is because you defined its color as Red. Change it to red and tooltips will work again :
datasets: [{
borderColor: 'red',
label: 'Capital R in borderColor, tooltips now work',
data: [
// ...
]
}]
You can see all these fixes live in this jsFiddle, and here is the final result :
Using ChartJs (v2.2.2) can you change the line style between the last 2 points on a graph. e.g. have a solid line all the way and then dashed at the end? see picture below
The borderDashproperty (scroll to Line Configuration) is the key to your problem.
The thing is, the full chart is drawn with a border dash, you cannot choose where it starts and where it ends.
A simple workaround is to create two identical datasets. One dotted and one with a plain line. Then you remvoe the last data of your plain one, and they both will be displayed as how you want it.
You can see the full code in this jsFiddle, and here is its result :
Note :
Since there are two datasets now, the legend will display both of them. Setting the display to false fixes it (more or less).
The declaration order doesn't matter since the plain line will always overwrite the dotted one.
Having a bezier curve (tension property > 0) can create a display problem since the data is not the same in both datasets.
You can create a scatter chart and draw the lines directly on the canvas using the Plugin Core API. The API offers a range of hooks that can be used for performing custom code. The advantage of this approach is that you can customize the style of every single connection line (width, color, dash pattern etc.).
const labels = [1, 2, 3, 4, 5, 6];
const values = [12, 19, 3, 5, 2, 3];
const data = labels.map((label, index) => ({ x: label, y: values[index]}));
var lineChart = new Chart(document.getElementById("chart"), {
type: "scatter",
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-1'];
var yAxis = chart.scales['y-axis-1'];
chart.config.data.datasets[0].data.forEach((value, index) => {
if (index > 0) {
var valueFrom = data[index - 1];
var xFrom = xAxis.getPixelForValue(valueFrom.x);
var yFrom = yAxis.getPixelForValue(valueFrom.y);
var xTo = xAxis.getPixelForValue(value.x);
var yTo = yAxis.getPixelForValue(value.y);
ctx.save();
ctx.strokeStyle = '#922893';
ctx.lineWidth = 2;
if (index + 1 == data.length) {
ctx.setLineDash([5, 10]);
}
ctx.beginPath();
ctx.moveTo(xFrom, yFrom);
ctx.lineTo(xTo, yTo);
ctx.stroke();
ctx.restore();
}
});
}
}],
data: {
datasets: [{
label: "My Dataset",
data: data,
borderColor: '#922893',
pointBackgroundColor: "transparent"
}]
},
options: {
legend: {
display: false
},
scales: {
xAxes: [{
ticks: {
stepSize: 1
}
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="chart" height="90"></canvas>
const labels = [1, 2, 3, 4, 5, 6];
const values = [12, 19, 3, 5, 2, 3];
const data = labels.map((label, index) => ({ x: label, y: values[index]}));
var lineChart = new Chart(document.getElementById("chart"), {
type: "scatter",
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-1'];
var yAxis = chart.scales['y-axis-1'];
chart.config.data.datasets[0].data.forEach((value, index) => {
if (index > 0) {
var valueFrom = data[index - 1];
var xFrom = xAxis.getPixelForValue(valueFrom.x);
var yFrom = yAxis.getPixelForValue(valueFrom.y);
var xTo = xAxis.getPixelForValue(value.x);
var yTo = yAxis.getPixelForValue(value.y);
ctx.save();
ctx.strokeStyle = '#922893';
ctx.lineWidth = 2;
if (index + 1 == data.length) {
ctx.setLineDash([5, 10]);
}
ctx.beginPath();
ctx.moveTo(xFrom, yFrom);
ctx.lineTo(xTo, yTo);
ctx.stroke();
ctx.restore();
}
});
}
}],
data: {
datasets: [{
label: "My Dataset",
data: data,
borderColor: '#922893',
pointBackgroundColor: "transparent"
}]
},
options: {
legend: {
display: false
},
scales: {
xAxes: [{
ticks: {
stepSize: 1
}
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="chart" height="90"></canvas>