Chartjs - Line between two dots on the Y axis - chart.js

The goal is to link 2 dots by a line.
Dots's datas are from 2 different arrays.
Here an image to help understand
https://i.stack.imgur.com/pe3WU.png

You can use a custom plugin for this:
const customLine = {
id: 'customLine',
beforeDatasetsDraw: (chart, args, options) => {
const {
ctx,
scales: {
x,
y
}
} = chart;
chart.data.datasets[0].data.forEach((dataPoint, i) => {
ctx.strokeStyle = options.lineColor || 'black';
ctx.lineWidth = options.lineWidth || 1;
ctx.beginPath();
ctx.moveTo(x.getPixelForValue(chart.data.labels[i]), y.getPixelForValue(dataPoint));
ctx.lineTo(x.getPixelForValue(chart.data.labels[i]), y.getPixelForValue(chart.data.datasets[1].data[i]));
ctx.stroke();
})
}
}
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1,
showLine: false,
backgroundColor: 'red'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1,
showLine: false,
backgroundColor: 'blue'
}
]
},
options: {
plugins: {
customLine: {
lineColor: 'pink',
lineWidth: 3
}
}
},
plugins: [customLine]
}
var 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.3.0/chart.js"></script>
</body>

Related

Legend on chart.js

I'm trying to make a legend with a perfect box, but I don't know how, the "NĂ­vel Op. Max" is not like the others,I think the reason this happens is because it's a dotted line and the others are solid lines.
Does anyone know if there is any property in chart.js that causes the square's edge to not be dotted?
My code:
legend: {
display: true,
labels: {
fontSize: 10,
boxWidth: 10
}
The way I want:
You can provide a custom generateLabels function and dont provide the setting for making the border dashed like so:
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'orange',
borderDash: [2, 2]
}
]
},
options: {
plugins: {
legend: {
labels: {
generateLabels: (chart) => {
const datasets = chart.data.datasets;
const {
labels: {
usePointStyle,
pointStyle,
textAlign,
color
}
} = chart.legend.options;
return chart._getSortedDatasetMetas().map((meta) => {
const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
const borderWidth = Chart.helpers.toPadding(style.borderWidth);
return {
text: datasets[meta.index].label,
fillStyle: style.backgroundColor,
fontColor: color,
hidden: !meta.visible,
lineCap: style.borderCapStyle,
lineDashOffset: style.borderDashOffset,
lineJoin: style.borderJoinStyle,
lineWidth: (borderWidth.width + borderWidth.height) / 4,
strokeStyle: style.borderColor,
pointStyle: pointStyle || style.pointStyle,
rotation: style.rotation,
textAlign: textAlign || style.textAlign,
borderRadius: 0,
datasetIndex: meta.index
};
})
}
}
}
}
}
}
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.6.2/chart.js"></script>
</body>

Catch event of show and hide dataset at chart.js

I'm using Chart.JS with chartjs-plugin-annotation for drawing base line in chart bar. And I wanna hide it ( this red line) when hide first data set.
let data1 = {
labels: charts['str-err'].labels,
datasets: [{
label: 'Strength',
data: charts['str-err'].data,
backgroundColor: ['rgba(0,102,204,0.5)']
},{
label: 'Avg data, %',
data: p_model,
backgroundColor: ['rgba(0,102,204,0.6)']
}]
};
let options = {
scales: {
x: {
grid: {
drawBorder: false,
display: false,
}
},
y: {
grid: {
drawBorder: false,
display: true,
drawOnChartArea: true,
drawTicks: false,
borderDash: [5, 5]
}
}
},
plugins: {
legend:{align: 'start'},
annotation: {
annotations: {
line1: {
type: 'line',
yMin: avg_err,
yMax: avg_err,
borderColor: 'rgba(234,6,6,0.7)',
borderWidth: 1,
borderDash: [2,2],
display: true
}
}
}
},
};
I wanna hide line1 when 'Strength' dataset was hidden, and turn it back when show 'Strength' chart bar. I know how to hide line1 but can't understand how to catch event that dataset was hidden
let displayAnnotation = function(chart, d){
chart.options.plugins.annotation.annotations.line1.display = d;
chart.update();
};
Thx
You can make use of the legend onClick handler like so:
const defaultLegendClickHandler = Chart.defaults.plugins.legend.onClick;
const pieDoughnutLegendClickHandler = Chart.controllers.doughnut.overrides.plugins.legend.onClick;
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: 'Strength',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
},
{
label: 'Avg data, %',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'orange'
}
]
},
options: {
plugins: {
legend: {
onClick: (evt, legendItem, legend) => {
const type = legend.chart.config.type;
if (type === 'pie' || type === 'doughnut') {
pieDoughnutLegendClickHandler(evt, legendItem, legend)
} else {
defaultLegendClickHandler(evt, legendItem, legend);
}
if (legendItem.text !== 'Strength') {
return;
}
legend.chart.options.plugins.annotation.annotations.line1.display = !legend.chart.getDatasetMeta(0).hidden;
legend.chart.update();
}
},
annotation: {
annotations: {
line1: {
type: 'line',
yMin: 4,
yMax: 6,
borderColor: 'rgba(234,6,6,0.7)',
borderWidth: 1,
borderDash: [2, 2],
display: 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.5.1/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/1.0.2/chartjs-plugin-annotation.js"></script>
</body>

Is there a way to highlight a line on a line graph with hover?

I am going to be using chart.js to build a graph like this:
It would be very useful to be able to allow the user to hover over a line on the graph and have that line highlight in some manner. How would I go about doing that with chart.js?
Thanks!
You can use the onHover callback for this in the options:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: '#FF0000',
borderColor: '#FF0000'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
backgroundColor: '#0000FF',
borderColor: '#0000FF'
},
{
label: '# of Cars',
data: [18, 4, 12, 6, 9, 2],
backgroundColor: '#FF1493',
borderColor: '#FF1493'
}
]
},
options: {
onHover: (e, activeEls, chart) => {
if (activeEls.length === 0) {
chart.data.datasets.forEach((dataset) => {
dataset.backgroundColor = dataset.backgroundColor.length === 9 ? dataset.backgroundColor.slice(0, -2) : dataset.backgroundColor;
dataset.borderColor = dataset.borderColor.length === 9 ? dataset.borderColor.slice(0, -2) : dataset.borderColor;
});
chart.update();
return;
}
const hoveredEl = chart.getElementsAtEventForMode(e, 'point', {
intersect: true
}, true)[0]
chart.data.datasets.forEach((dataset, i) => {
dataset.backgroundColor = (hoveredEl.datasetIndex === i || dataset.backgroundColor.length === 9) ? dataset.backgroundColor : dataset.backgroundColor + '4D';
dataset.borderColor = (hoveredEl.datasetIndex === i || dataset.borderColor.length === 9) ? dataset.borderColor : dataset.borderColor + '4D';
});
chart.update();
},
}
}
var 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.4.0/chart.js"></script>
</body>

Chart.js V3 Fill Below 0

I'm looking for a way to fill everything below 0 on my graph as a nice shade of red. After scouring SO and the documentation, I haven't been able to find a way to do this. I tried creating a dataset filled with decimal.MinValue and setting everything below 0 as filled, but it shifted the entire graph down to the min regardless of whether the dataset was set to be hidden or not. Any advise would be greatly appreciated. Thank you.
You can use a custom inline plugin for this:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [100, 19, 3, 5, -10, 3],
borderColor: 'red',
backgroundColor: 'red'
},
{
label: '# of Votes2',
data: [20, 10, 4, 3, -30, 32],
borderColor: 'blue',
backgroundColor: 'blue'
}
]
},
options: {
plugins: {
backgrounds: {
hbars: [{
from: 0,
to: 'MIN',
color: "rgb(230, 195, 195)"
}]
}
}
},
plugins: [{
id: 'backgrounds',
beforeDraw: (chart, args, options) => {
const {
canvas,
ctx,
chartArea,
scales: {
y
}
} = chart;
let from = 0;
let to = 0;
options.hbars.forEach((hBar) => {
from = hBar.from;
to = hBar.to;
from = from === 'MIN' ? y.min : from;
from = from === 'MAX' ? y.max : from;
to = to === 'MIN' ? y.min : to;
to = to === 'MAX' ? y.max : to;
ctx.save(canvas.width, canvas.height);
ctx.fillStyle = hBar.color;
ctx.fillRect(chartArea.left, y.getPixelForValue(from), chartArea.right - chartArea.left, y.getPixelForValue(to) - y.getPixelForValue(hBar.from));
ctx.restore();
})
}
}]
}
var 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.4.0/chart.js"></script>
</body>

Chartjs - display radarchart lines from center to corner value

Is there a way to achieve for radarchart from chartjs to display line from center (value 0) to value of the corner? It would looks something like this:
radarchart_image
This is possible by writing a custom inline plugin like so:
var options = {
type: 'radar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
plugins: {
customLine: {
//specify line color
lineColor: 'red'
}
}
},
plugins: [{
id: 'customLine',
afterDatasetDraw: (chart, args, options) => {
const {
ctx,
chartArea
} = chart;
const {
meta
} = args;
// only do the first dataset lines, if you remove this if it will draw lines for all datasets
if (meta.index > 0) {
return;
}
meta.data.forEach((dataPoint) => {
//default line color black as fallback if no color is specified
ctx.strokeStyle = options.lineColor || 'black';
ctx.beginPath();
ctx.moveTo(chartArea.width / 2, chartArea.height / 2 + chartArea.top);
ctx.lineTo(dataPoint.x, dataPoint.y);
ctx.stroke();
})
}
}]
}
var 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.1.0/chart.js" integrity="sha512-LlFvdZpYhQdASf4aZfSpmyHD6+waYVfJRwfJrBgki7/Uh+TXMLFYcKMRim65+o3lFsfk20vrK9sJDute7BUAUw==" crossorigin="anonymous"></script>
</body>