HTML Canvas 渐变只显示一种颜色
我在使用 Canvas gradient 时遇到问题,它只显示我在 gradient.__addColorStop__(offset,color)
方法上设置的最后一种颜色.
I'm having problems with Canvas gradient it only shows the last color that I set on gradient.__addColorStop__(offset,color)
method.
例如,这是我更好理解的一段代码:
For example here is a piece of my code to understand better:
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let gradient = ctx.createLinearGradient(10, 90, 200, 90);
gradient.addColorStop(1 / 10, "black");
gradient.addColorStop(1 / 5, "yellow");
gradient.addColorStop(1 / 1, "red");
let circle1 = new Circle(300, 250, 50, gradient);
circle1.draw(ctx);
该代码仅绘制一个红色圆圈,并对填充渐变的任何形状执行相同操作,如果我评论此行 gradient.addColorStop(1/1,"red");
然后画布绘制一个黄色圆圈,只读取最后一个颜色.我在 jsfiddle.net 上尝试了相同的代码并且运行良好,但我不知道为什么我的脚本无法运行.
That code only draw a red circle and do the same with any shape filled with the gradient, if i comment this line gradient.addColorStop(1/1,"red");
then canvas draw a yellow circle, only read the last color. I tried the same code on jsfiddle.net and works perfectly, i dont know why my script wont work.
PD:Circle 是我定义的一个 js 对象,可以完美运行
PD: Circle is a js object that i defined and works perfectly
对不起我的英语,如果帖子听不懂请告诉我,这是我在 StackOverflow 上的第一篇帖子.谢谢!
Sorry for my english, if the post doesn't understand please tell me, is my first post on StackOverflow. Thanks!
推荐答案
CanvasGradients 是相对于上下文的转换矩阵,而不是你要填充它的形状.
CanvasGradients are relative to the context's transformation matrix, not to the shape you'll fill it with.
因此,在您的示例中,由于您正在绘制水平渐变,因此您只能在从 x:10 到 x:200 的区域中设置此渐变.x:10 之前的像素将具有索引 0 处的值,x:200 之后的像素将具有索引 1 处的值.
由于您在 300,150 处绘制半径为 50 的圆,因此您的圆将达到的最小 x 位置为 250,这在您的渐变索引:1 之后,因此为纯红色.
So in your example, since you are drawing an horizontal gradient, you set this gradient only in an area that goes from x:10 to x:200. Pixels before x:10 will have the value at index 0, and the ones after x:200 the one at index 1.
Since you are drawing your circle at 300,150 with a radius of 50, the minimal x position your circle will attain is 250, which is after your gradient index:1 and hence solid red.
这里是发生了什么的视觉演示:
Here is a visual demo of what happens:
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let gradient = ctx.createLinearGradient(10, 90, 200, 90);
gradient.addColorStop(1 / 10, "black");
gradient.addColorStop(1 / 5, "yellow");
gradient.addColorStop(1 / 1, "red");
// draw a full rectangle to see how the gradient is actually rendered
ctx.fillStyle = gradient;
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
ctx.arc(300, 150, 50, 0, Math.PI*2);
ctx.strokeStyle = 'white';
ctx.stroke();
<canvas id="canvas" width="500" height="300"></canvas>
要避免这种情况,您有两种方法:
To circumvent this, you have two ways:
- 在正确的坐标处生成 CanvasGradient:
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
// x1 & x2 are set to match the circle's position
let gradient = ctx.createLinearGradient(250, 90, 350, 90);
gradient.addColorStop(1 / 10, "black");
gradient.addColorStop(1 / 5, "yellow");
gradient.addColorStop(1 / 1, "red");
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(300, 150, 50, 0, Math.PI*2);
ctx.fill();
<canvas id="canvas" width="500" height="300"></canvas>
- 修改上下文的转换矩阵以移动 CanvasGradient:
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let gradient = ctx.createLinearGradient(10, 90, 200, 90);
gradient.addColorStop(1 / 10, "black");
gradient.addColorStop(1 / 5, "yellow");
gradient.addColorStop(1 / 1, "red");
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(300, 150, 50, 0, Math.PI*2);
// our arc has been defined at the correct position
// we can now translate the context matrix so that only the fillStyle be moved
ctx.translate(230, 0);
ctx.fill();
// reset the default tranform matrix
ctx.setTransform(1,0,0,1,0,0);
<canvas id="canvas" width="500" height="300"></canvas>
相关文章