繁体   English   中英

CSS 线性梯度不准确?

[英]CSS Linear gradient is inaccurate?

对于我的应用程序,我正在寻找可以提供从 0 度到 360 度的任何色调的调色板。 我目前正在使用此代码来制作调色板。 让我们以色调 120(纯绿色)为例:

 function drawPalette(hue) { var ctx = document.querySelector("canvas").getContext("2d"); let w = ctx.canvas.width; let h = ctx.canvas.height; var grH = ctx.createLinearGradient(0, 0, w, 0); grH.addColorStop(0, '#fff'); grH.addColorStop(1, 'hsl(' + hue + ', 100%, 50%)'); ctx.fillStyle = grH; ctx.fillRect(0, 0, w, h); var grV = ctx.createLinearGradient(0, 0, 0, h); grV.addColorStop(0, 'rgba(0,0,0,0)'); grV.addColorStop(1, '#000'); ctx.fillStyle = grV; ctx.fillRect(0, 0, w, h); } drawPalette(120);
 <canvas></canvas>

我遇到的问题是这似乎不是一个完美的渐变。 例如,右上角的颜色是#02FF02而不是#00FF00 (纯绿色)。 您可以使用颜色选择器自己查看。

有没有办法制作可用于调色板的完美线性渐变?

不,渐变返回正确的结果。 右上角的像素位于渐变的起点和终点之间,并有一个插值来反映这一点。

想象一个具有单一水平或垂直渐变的单像素 canvas。 渐变的起点是 [0,0],渐变的终点是 [1,0]。 我们唯一像素的中间应该有一个介于开始值和结束值之间的值。 如果我们的起始值为 255,255,255,结束值为 0,255,0,那么唯一的像素应该是 128,255,128,如下所示:

 function drawPalette(hue) { var ctx = document.querySelector("canvas").getContext("2d"); let w = ctx.canvas.width; let h = ctx.canvas.height; var grH = ctx.createLinearGradient(0, 0, w, 0); grH.addColorStop(0, '#fff'); grH.addColorStop(1, 'hsl(' + hue + ', 100%, 50%)'); ctx.fillStyle = grH; ctx.fillRect(0, 0, w, h); let data = ctx.getImageData(w-1,0, 1, 1).data; console.log(data); } drawPalette(120);
 <canvas width="1" height="1"></canvas>

如果我们有一个 10 像素乘 10 像素的 canvas,渐变从 0 延伸到 10,最后一列像素的中间超过 9.5 像素。 这意味着,渐变的插值应该是渐变的开始值和结束值之间的 95%。 使用与上面相同的梯度,应该是:13、255、13:

 function drawPalette(hue) { var ctx = document.querySelector("canvas").getContext("2d"); let w = ctx.canvas.width; let h = ctx.canvas.height; var grH = ctx.createLinearGradient(0, 0, w, 0); grH.addColorStop(0, '#fff'); grH.addColorStop(1, 'hsl(' + hue + ', 100%, 50%)'); ctx.fillStyle = grH; ctx.fillRect(0, 0, w, h); let data = ctx.getImageData(w-1,0, 1, 1).data; console.log(data); } drawPalette(120);
 <canvas width="10" height="10"></canvas>

随着 canvas 变大,应用梯度的第一个/最后一个值与梯度开始/结束值之间的差异减小。 如果您将示例中的 canvas 更改为 1000x1000 的大小,则由于四舍五入,右上角的像素将具有 0,255,0 的值:

 function drawPalette(hue) { var ctx = document.querySelector("canvas").getContext("2d"); let w = ctx.canvas.width; let h = ctx.canvas.height; var grH = ctx.createLinearGradient(0, 0, w, 0); grH.addColorStop(0, '#fff'); grH.addColorStop(1, 'hsl(' + hue + ', 100%, 50%)'); ctx.fillStyle = grH; ctx.fillRect(0, 0, w, h); var grV = ctx.createLinearGradient(0, 0, 0, h); grV.addColorStop(0, 'rgba(0,0,0,0)'); grV.addColorStop(1, '#000'); ctx.fillStyle = grV; ctx.fillRect(0, 0, w, h); let data = ctx.getImageData(w-1,0, 1, 1).data; console.log(data); } drawPalette(120);
 <canvas width="1000" height="1000"></canvas>

渐变包括起点和终点之间的像素。 如果您不希望它们被渐变化,那么您必须修改渐变,使其晚一个像素开始并早一点结束:

 function drawPalette(hue) { var ctx = document.querySelector("canvas").getContext("2d"); let w = ctx.canvas.width; let h = ctx.canvas.height; // to ensure we know we're covering the whole thing: ctx.fillRect(0,0,w,h) // var grH = ctx.createLinearGradient(1, 0, w-2, 0); grH.addColorStop(0, '#fff'); grH.addColorStop(1, 'hsl(' + hue + ', 100%, 50%)'); ctx.fillStyle = grH; ctx.fillRect(0, 0, w, h); let data = ctx.getImageData(w-1,0, 1, 1).data; console.log(data); } drawPalette(120);
 <canvas width="100" height="100"></canvas>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM