The background color of the datasets from my stacked line chart mix with each other, just like below.
This is my code:
var chart = new Chart($('#chart-area'), {
type: "line",
data: {
labels: [],
datasets: [],
},
options: {
responsive: true,
maintainAspectRatio: false,
hover: {
mode: 'index',
intersect: false
},
scales: {
yAxes: [{
stacked: true
}]
}
},
});
And I dynamically create the datasets:
chart.data.datasets.push({
label: LABELS,
borderColor: COLOR1,
backgroundColor: COLOR2,
data: []
});
My colors example:
COLOR1 -> "#000c89",
COLOR2 -> 'rgba(0, 12, 137, 0.4)'
Any idea how to make the colors look like their normal? They get mixed (I think it's because of the transparency), I can make them without transparency, but the chart gets ugly.
Indeed, the colours mix because of the transparency. I don't think it's possible to avoid that effect, since the only reason there's a transparency channel in rgba
is to allow that mixing of "foreground" and "background" colours.
Indeed, rgba
is not supposed to provide more colours than rgb
.
The nice colours you get by using rgba
in chart.js backgrounds are the result of combining the rgb
part of that color as "foreground" with the chart background which is typically white (rgb(255, 255, 255)
). The components of the resulting rgb mix can be computed with
rMix = Math.round(r * a + 255 * (1 - a))
gMix = Math.round(g * a + 255 * (1 - a))
bMix = Math.round(b * a + 255 * (1 - a))
Here's a code snippet doing that calculation
function runColors() {
const ctxRgba = document.querySelector('#cvs_rgba').getContext('2d'),
ctxRgb = document.querySelector('#cvs_rgb').getContext('2d'),
textRgba = document.querySelector('#rgba'),
textRgb = document.querySelector('#rgb');
textRgba.innerText = '';
textRgb.innerText = '';
ctxRgba.fillStyle = 'rgb(255,255,255)';
ctxRgba.fillRect(0, 0, 300, 150);
ctxRgb.fillStyle = 'rgb(255,255,255)';
ctxRgb.fillRect(0, 0, 300, 150);
const r = parseInt(document.querySelector('#r').value, 10),
g = parseInt(document.querySelector('#g').value, 10),
b = parseInt(document.querySelector('#b').value, 10),
a = parseFloat(document.querySelector('#a').value);
if (r < 0 || r > 255 || b < 0 || b > 255 || g < 0 || g > 255 || a < 0 || a > 1) {
document.querySelector('#error').innerText = 'Invalid data';
return;
}
document.querySelector('#error').innerText = '';
const sRGBA = `rgba(${r},${g},${b},${a.toFixed(4).replace(/0+$/, '')})`;
textRgba.innerText = sRGBA;
const r1 = Math.round(r * a + 255 * (1 - a)),
b1 = Math.round(b * a + 255 * (1 - a)),
g1 = Math.round(g * a + 255 * (1 - a));
const sRGB = `rgb(${r1},${g1},${b1})`;
textRgb.innerText = sRGB;
ctxRgba.fillStyle = sRGBA;
ctxRgba.fillRect(0, 0, 300, 150);
ctxRgb.fillStyle = sRGB;
ctxRgb.fillRect(0, 0, 300, 150);
}
runColors();
<body>
<h3>
<code>rgb</code> result of mixing an <code>rgba</code> color with a white background
</h3>
R:<input type="text" size="3" value="0" id="r" onchange="runColors()"> G:
<input type="text" size="3" value="12" id="g" onchange="runColors()"> B:
<input type="text" size="3" value="137" id="b" onchange="runColors()"> A:
<input type="text" size="5" value="0.4" id="a" onchange="runColors()">
<div id="error" style="color:red"></div>
<div style="display: inline-block; border:1px solid black">
<canvas id="cvs_rgba" style="width: 200px; height: 50px;background-color: rgb(255, 255, 255)"></canvas>
<br>
<code id="rgba"></code>
</div>
<div style="display: inline-block; border:1px solid black">
<canvas id="cvs_rgb" style="width: 200px; height: 50px;background-color: rgb(255, 255, 255)"></canvas>
<br>
<code id="rgb"></code>
</div>
also as a jsFiddle.
Addendum
Note: I have to add what I know theoretically about the topic of wide gamut colours as it is indirectly relevant to the question asked; however, this is only abstract information as I never used these color spaces, nor do I have a HDR monitor. Please contribute to this (message/new answer/edit/downvote) if you know more.
Insofar wider-than-rgb(24) color spaces are concerned, that is a large topic, but it's worth mentioning the fact that (at the time of posting, end of 2023) there's already good support for it in browsers. One may start with simple but good introductions like this one or read the specs in css4 and the githb canvas-color-space pages.
A simple test shows that chart.js doesn't complain if one uses backgroundColor: "color(display-p3 0 1 0)"
but passes that color to the canvas functions. This means one can write wide-gamut ready code for chart.js. However, the way the canvas context is created in the code, seems to indicate that there's currently no way for users to set the color space, not even if a CanvasRenderingContext2d
is passed as the first argument to the Chart
constructor.