Catch event of show and hide dataset at chart.js - 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>

Related

Can I make Y axis begin at specific value in ChartJS?

I have this chart, starting at 0 and I want the Y axis to begin at 20. It surprises me how there is nothing related to this in the official ChartJS docs. Is this possible in any way?
I have tried several ways to do it, eg. with ticks or min value and so on but nothing worked.
The application is written in Nuxt3 and the ChartJS library used is vue-chart-3.
const options = computed(() => ({
responsive: true,
plugins: {
legend: {
display: false,
},
title: {
display: false,
}
},
scales: {
x: {
stacked: true,
},
y: {
stacked: true,
}
}
}));
const chartData = computed(() => ({
labels: ['Provider'],
datasets: [
{
data: [selectedDataset.value?.score.uncustomized],
backgroundColor: ['#00b7c4'],
},
{
data: [selectedDataset.value?.score.difference],
backgroundColor: ['#204992'],
},
],
}));
const { barChartProps, barChartRef } = useBarChart({
chartData,
options,
});
Any help would be appreciated.
If you want the axis to start at a given number you need to use the min property:
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'
}
]
},
options: {
scales: {
y: {
min: 6
}
}
}
}
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>

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>

Chartjs - Line between two dots on the Y axis

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>

padding not working in my chartjs line-graph

I'm using the newest version of chart.js (3.2.1). Padding works if I'm set it to positive values.
But padding 0 (or negative values) doesn't set the line graph exactly at the borders of canvas
options: {
layout: {
padding:0
},
interaction: {
intersect: false,
},
plugins: {
tooltip: {
backgroundColor: 'transparent',
displayColors: false,
bodyFontSize: 14,
titleColor: 'rgba(83,255,228,1)',
callbacks: {
label: function (tooltipItems, data) {
return 'BMI: ' + tooltipItems.raw;
}
}
},
legend: {
display: false,
},
},
elements: {
point: {
radius: 6,
hitRadius: 6,
hoverRadius: 6
}
},
scales: {
xAxes: {
display: false,
},
yAxes: {
display: false,
},
}
}
The padding in the chart config is not for styling of the canvas to other elements, the only thing the padding does is adding the ability of making a bit of space between the canvas edge and the line, from the image you provided it seems like it goes to the end of the canvas and the empty space is another element beneath the canvas.
As you can see in this example, the canvas background is colored gray and with padding: 0 the line touches the end of the canvas as expected
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
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
plugins: {
tooltip: {
backgroundColor: 'transparent',
displayColors: false,
bodyFontSize: 14,
titleColor: 'rgba(83,255,228,1)',
callbacks: {
label: function(tooltipItems, data) {
return 'BMI: ' + tooltipItems.raw;
}
}
},
legend: {
display: false,
},
},
interaction: {
intersect: false,
},
layout: {
padding: 0
},
elements: {
point: {
radius: 0
}
},
scales: {
y: {
display: false
},
x: {
display: false
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
canvas {
background-color: #eee;
}
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.2.0/chart.js" integrity="sha512-opXrgVcTHsEVdBUZqTPlW9S8+99hNbaHmXtAdXXc61OUU6gOII5ku/PzZFqexHXc3hnK8IrJKHo+T7O4GRIJcw==" crossorigin="anonymous"></script>
</body>

ChartJS with Dynamic Colors

I saw your post regarding,
Instead of just "Stock" at the left, is there anyway to put a separate label for each bar, eg 18, 82, 22, 80 going down the y-axis?
Below is the link which I'm referring ...
ChartJS bar chart with legend which corresponds to each bar
You are looking for something like the following:
var chart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: [18, 82, 22, 80],
datasets: [{
data: [1, 2, 3, 4],
backgroundColor: ['#ff6384', '#36a2eb', '#ffce56', '#4bc0c0', '#9966ff'],
borderColor: ['#ff6384', '#36a2eb', '#ffce56', '#4bc0c0', '#9966ff']
}]
},
options: {
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
},
legend: {
labels: {
generateLabels: function(chart) {
var labels = chart.data.labels;
var dataset = chart.data.datasets[0];
var legend = labels.map(function(label, index) {
return {
datasetIndex: 0,
text: label,
fillStyle: dataset.backgroundColor[index],
strokeStyle: dataset.borderColor[index],
lineWidth: 1
}
});
return legend;
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="ctx"></canvas>