Chart.js V3 Fill Below 0 - chart.js

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>

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>

How to get chart size (without labels) with chart.js?

Now i have this chart:
https://codepen.io/UnluckySerivelha/pen/BawpPYv
const ctx = document.getElementById('graph').getContext('2d');
var bar_ctx = document.getElementById('graph').getContext('2d');
x=["14 Dec","15 Dec"];
y1={"14 Dec":0,"15 Dec":0,};
y2={"14 Dec":0,"15 Dec":0,};
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: x,
datasets: [
{
label: 'Всего за день',
data: y1
},
{
label: 'Будет начислено по вкладам',
data: y2,
},
]
},
options: {
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value, index, values) {
return '$ ' + value;
}
}
}
},
responsive: true,
maintainAspectRatio: false
},
});
I want to add background image for chart area, but not for labels. I know how to add background image, but don't know how to get size of chart area without labels for assignment size and position of image. Is it possible?
You can check the chartArea property that is available in the chart context. This property has the width and height of the area where the chart itself is being drawn.
const 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: {}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
const chart = new Chart(ctx, options);
console.log('height: ', chart.chartArea.height);
console.log('width: ', chart.chartArea.width)
<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>
Your own code with the background colored pink: https://codepen.io/leelenaleee/pen/OJxWoPe
Official example on using an image as background: https://www.chartjs.org/docs/master/configuration/canvas-background.html#image

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>

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>