简体   繁体   English

CSS 线性梯度不准确?

[英]CSS Linear gradient is inaccurate?

For my application I'm looking to make a color palette that can serve any color hue from 0 degrees to 360 degrees.对于我的应用程序,我正在寻找可以提供从 0 度到 360 度的任何色调的调色板。 I'm currently using this code to make the palette.我目前正在使用此代码来制作调色板。 Let's use hue 120 (pure green) as an example:让我们以色调 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>

The issue I'm having is that this doesn't seem to be a perfect gradient.我遇到的问题是这似乎不是一个完美的渐变。 For example, the color at the top right is #02FF02 instead of #00FF00 (pure green).例如,右上角的颜色是#02FF02而不是#00FF00 (纯绿色)。 You can use a color picker to see this for yourself.您可以使用颜色选择器自己查看。

Is there any way to make a perfect linear gradient that is usable for a color palette?有没有办法制作可用于调色板的完美线性渐变?

No, the gradient is returning the correct result.不,渐变返回正确的结果。 The top right pixel is between the start and end points of the gradient, and has an interpolated value to reflect that.右上角的像素位于渐变的起点和终点之间,并有一个插值来反映这一点。

Imagine a single pixel canvas with a single horizontal or vertical gradient.想象一个具有单一水平或垂直渐变的单像素 canvas。 The gradient's start point is [0,0] and the gradient's end is [1,0].渐变的起点是 [0,0],渐变的终点是 [1,0]。 The middle of our sole pixel should have a value half way between the start and end values.我们唯一像素的中间应该有一个介于开始值和结束值之间的值。 If our start value is 255,255,255 and the end value is 0,255,0, then the sole pixel should be 128,255,128, as seen below:如果我们的起始值为 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>

If we have a ten pixel by ten pixel canvas, the gradient stretches from 0 to 10, with the middle of the last column of pixels being 9.5 pixels over.如果我们有一个 10 像素乘 10 像素的 canvas,渐变从 0 延伸到 10,最后一列像素的中间超过 9.5 像素。 Which means, the gradient's interpolated value should be 95% of the way between the start and end values of the gradient.这意味着,渐变的插值应该是渐变的开始值和结束值之间的 95%。 Using the same gradient as above, that should be: 13, 255, 13:使用与上面相同的梯度,应该是: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>

As the canvas gets bigger, the difference between the first/last values with the applied gradient and the gradient start/end values decreases.随着 canvas 变大,应用梯度的第一个/最后一个值与梯度开始/结束值之间的差异减小。 If you change the canvas in your example to have a size of 1000x1000, the top right pixel will have a value of 0,255,0 due to rounding:如果您将示例中的 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>

The gradient includes the pixels between the start and end points.渐变包括起点和终点之间的像素。 If you don't want them to be gradient-ized, then you'll have to modify the gradient so that it starts one pixel later and ends one pixel sooner:如果您不希望它们被渐变化,那么您必须修改渐变,使其晚一个像素开始并早一点结束:

 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