In ChartJS one can change the point style to some predefined forms. But I need the point style to be an arrow so I tried to customize the point style but didn't succeed. I tried the following:
customTrianglePointStyle: function (ctx) {
const path = new Path2D();
const radius = 10;
path.moveTo(0, -radius);
path.lineTo(radius, radius);
path.lineTo(-radius, radius);
path.closePath();
return path;
},
and add it to the dataset
let dataset = {
data: JSON.parse(jsonData),
yAxisID: "y",
showLine: false,
pointRadius: 5,
pointStyle: this.customTrianglePointStyle,
}
But it falls back to the default point style.
In the documentation I found:
When a string is provided, the following values are supported: 'circle' 'cross' 'crossRot' 'dash' 'line' 'rect' 'rectRounded' 'rectRot' 'star' 'triangle' false If the value is an image or a canvas element, that image or canvas element is drawn on the canvas using drawImage
But in my case I don't want to draw an image but a shape on the canvas at each plot point.
Has someone an idea how I could achieve my goal.
As C3roe
explained in the comments, and as is also stated in the documentation page you quoted from, you may provide the pointStyle
as an HTMLCanvasElement
(or an ImageElement
). So, to set a custom style drawn using a canvas, you have to create a new canvas element, draw on that canvas using its RenderingContext
and then 3) return the canvas (not the path).
function pointStyle(){
const canvas = document.createElement('canvas');
canvas.height = 20;
canvas.width = 20;
const ctx = canvas.getContext('2d');
const path = new Path2D();
const radius = 10;
path.moveTo(radius, 0);
path.lineTo(2*radius, 2*radius);
path.lineTo(0, 2*radius);
path.closePath();
ctx.strokeStyle = '#000';
ctx.fillStyle = 'red';
ctx.stroke(path);
ctx.fill(path);
return canvas;
}
The point style may be customised for each point, through the first argument received by the pointStyle
function, that contains all information regarding the data point (explore it with console.log
). You may use that information to rotate the points of the Path2D
around the center of the canvas.
However, we have a built-in point property for rotation, pointRotation
, which is also scriptable receiving the same arguments as pointStyle
(note that you may also use it to rotate a standard point style, like a triangle).
Assuming the rotation information in the data
is given as a rotate
entry for each data point (e.g., {x: 0, y: 25, rotate: 20}
) that contains the rotation of the point in degrees, the pointRotation
function can be:
function pointRotation(dataContext){
return dataContext.raw?.rotate ?? 0;
}
which is much simpler than implementing rotation at the pointStyle
level.
Demo stack snippet:
const dataXY = [
{x: 0, y: 25, rotate: 20},
{x: 100, y: 42, rotate: 80},
{x: 200, y: 35, rotate: 120}
];
function pointStyle(dataContext){
// dataContext may be used to customize the image
const canvas = document.createElement('canvas');
canvas.height = 20;
canvas.width = 20;
const ctx = canvas.getContext('2d');
const path = new Path2D();
const radius = 10;
path.moveTo(radius, 0);
path.lineTo(2*radius, 2*radius);
path.lineTo(0, 2*radius);
path.closePath();
ctx.strokeStyle = '#000';
ctx.fillStyle = 'red';
ctx.stroke(path);
ctx.fill(path);
return canvas;
}
function pointRotation(dataContext){
return dataContext.raw?.rotate ?? 0;
}
new Chart('myChart', {
type: 'line',
data: {
datasets: [{
label: 'Dataset 1',
data: dataXY
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
pointStyle: pointStyle,
pointRotation: pointRotation,
scales: {
x: {
type: 'linear',
min: -5,
max: 205,
ticks: {
includeBounds: false,
},
},
y:{
grace: 2
}
}
}
});
<div style="min-height: 250px">
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>