堆叠折线图中数据集的背景颜色相互混合,如下所示。
这是我的代码:
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
}]
}
},
});
我创建了动态数据集:
chart.data.datasets.push({
label: LABELS,
borderColor: COLOR1,
backgroundColor: COLOR2,
data: []
});
我的颜色示例:
COLOR1 -> "#000c89",
COLOR2 -> 'rgba(0, 12, 137, 0.4)'
有什么想法可以让颜色看起来像正常的吗?它们混合在一起(我认为这是因为透明度),我可以在没有透明度的情况下制作它们,但图表变得丑陋。
确实,由于透明度,颜色会混合。我认为不可能避免这种效果,因为
rgba
中存在透明通道的唯一原因是允许“前景”和“背景”颜色的混合。
确实,
rgba
不应该提供比 rgb
更多的颜色。
在 Chart.js 背景中使用
rgba
获得的漂亮颜色是将该颜色的 rgb
部分作为“前景”与通常为白色的图表背景 (rgb(255, 255, 255)
) 组合的结果。生成的 RGB 混合的分量可以用 计算
rMix = Math.round(r * a + 255 * (1 - a))
gMix = Math.round(g * a + 255 * (1 - a))
bMix = Math.round(b * a + 255 * (1 - a))
这是执行该计算的代码片段
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>
也可用作 jsFiddle。
附录
注意:我必须添加我理论上所了解的关于广色域颜色主题的知识,因为它与所提出的问题间接相关;然而,这只是抽象信息,因为我从未使用过这些色彩空间,也没有 HDR 显示器。如果您了解更多信息,请为此做出贡献(消息/新答案/编辑/否决)。
就比 rgb(24) 更宽的颜色空间而言,这是一个很大的话题,但值得一提的是(截至 2023 年底发布时)浏览器中已经对其提供了良好的支持。人们可以从简单但很好的介绍开始,比如 this one,或者阅读 css4 和 githb canvas-color-space 页面中的规范。
一项简单的测试表明,如果使用
backgroundColor: "color(display-p3 0 1 0)"
,chart.js 不会抱怨,而是将该颜色传递给画布函数。这意味着我们可以为 Chart.js 编写广域就绪代码。然而,代码中创建画布上下文的方式似乎表明用户当前无法设置颜色空间,即使将 CanvasRenderingContext2d
作为第一个参数传递给 Chart
构造函数也是如此。