我使用Path2D绘制了一个负轴路径,通过平移使其偏移,然后使用createPattern创建了一个渐变。我发现填充具有偏移量,并且Chrome浏览器上存在偏移量,这在Firefox浏览器中是正常的。为什么它们不同??
在Chrome和Firefox上打开此演示 https://codepen.io/xiechengjian/pen/vVbNXv。
我的Chrome版本:70.0.3538.67 我的Firefox版本:63.0
let p = new Path2D();
ctx.translate(100,100)
p.moveTo(-100,-100)
p.lineTo(100,-100);
p.lineTo(100,100);
p.lineTo(-100,100);
p.closePath()
var offCanvas = document.createElement('canvas');
offCanvas.width = 200;
offCanvas.height = 200;
var offCtx=offCanvas.getContext("2d")
offCtx.fillStyle = "red"
offCtx.fillRect(0,0,200,200);
let gradient = ctx.createPattern(offCanvas, "no-repeat");
ctx.fillStyle = gradient
ctx.fill(p)
ctx.stroke(p)
答案 0 :(得分:0)
首先,我想澄清一下我担心的误解。在与ctx.fill(p); ctx.stroke(p);
一起使用之前,您创建的Path2D对象始终未连接到2D上下文。
仅在这些方法中,其子路径的坐标才会转换为上下文的当前矩阵。
因此ctx.translate(100,100);
对Path2D对象没有影响,尽管对两个上下文的方法都有影响。
此外,您的Path2D实际上只是p.rect(-100, -100, 200, 200)
。
因此,如果我们将所有这些Path2D代码替换为一个简单的ctx.rect()
调用,就会发现您发现的差异与Path2D API无关:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = generatePattern();
ctx.translate(100, 100);
ctx.rect(-100, -100, 200, 200);
ctx.fill();
ctx.stroke();
function generatePattern() {
var offCanvas = document.createElement('canvas');
offCanvas.width = 200;
offCanvas.height = 200;
var offCtx = offCanvas.getContext("2d");
offCtx.fillStyle = "red";
offCtx.fillRect(0, 0, 200, 200);
return ctx.createPattern(offCanvas, "no-repeat");
}
<canvas id="canvas" width="500" height="250"></canvas>
那么发生的事情是fillStyle
(和strokeStyle
)属性就像一个无限大的层,它本身相对于上下文的转换矩阵。当您将其设置为CanvasPattern或CanvasGradient时,这很重要,因为位图的位置将由此转换矩阵确定。
这是一个简单的示例,显示了如何使用它来创建移动渐变,而子路径保持不变。
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// we define the gradient only once
ctx.fillStyle = generateGradient();
// we define the sub-path only once
ctx.lineTo(20, 20);
ctx.lineTo(190, 50);
ctx.lineTo(130, 190);
ctx.closePath();
draw({clientX:50, clientY:50});
canvas.onmousemove = draw;
function draw(evt) {
var rect = canvas.getBoundingClientRect();
var x = evt.clientX - rect.left - 50;
var y = evt.clientY - rect.top - 50;
// clear
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0,0,canvas.width,canvas.height);
// here, all that moves is the fillStyle layer
ctx.translate(x, y);
ctx.fill();
ctx.stroke();
}
function generateGradient() {
var grad = ctx.createRadialGradient(
50,
50,
0,
50,
50,
25
); // a circle whose center is at 50,50, and rad is 25
grad.addColorStop(0, 'red');
grad.addColorStop(1, 'green');
return grad;
}
move your mouse over the triangle
<canvas id="canvas" width="500" height="250"></canvas>
在您的情况下,您创建的图案将在x和y轴上移动100px,因此 offCanvas 的左上角将在像素100,100处渲染,并且由于仅路径直到像素200,200为止,它将被裁剪。
但是Firefox为什么会像没有偏移一样呈现它?
这完全是Firefox如何呈现非重复CanvasPatterns的错误。
使用位图图像将使其显而易见:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.onload = function() {
ctx.fillStyle = ctx.createPattern(img, "no-repeat");
ctx.translate(100, 100);
ctx.rect(-100, -100, 200, 200);
ctx.fill();
ctx.stroke();
};
img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png';
<canvas id="canvas" width="500" height="250"></canvas>
因此,当您使用纯红色作为图案时,此错误实际上会产生全红色的位图,而正确的行为according to specs是在图案算法未产生结果的情况下渲染透明的黑色像素。
要解决此问题,我们必须等待FF提供它。
但是请注意,在您的情况下,使用fillRect
可以解决该错误。
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.onload = function() {
ctx.fillStyle = ctx.createPattern(img, "no-repeat");
ctx.fillRect(0, 0, 200, 200);
ctx.strokeRect(0, 0, 200, 200);
};
img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png';
<canvas id="canvas" width="500" height="250"></canvas>