Я использовал Path2D для рисования пути отрицательной оси, смещения его с помощью translate, а затем создал градиент с 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)
Сначала я хотел бы прояснить, что я боюсь, это неправильное представление здесь. Созданный объект Path2D не подключен к вашему 2D-контексту так или иначе, прежде чем использовать его с ctx.fill(p); ctx.stroke(p);
ctx.fill(p); ctx.stroke(p);
,
Только внутри этих методов координаты его подпутей будут преобразованы в контекстную текущую матрицу.
Таким образом, ctx.translate(100,100);
не влияет на объект Path2D, но он будет иметь оба контекстных метода.
Кроме того, ваш Path2D на самом деле просто p.rect(-100, -100, 200, 200)
. Поэтому, если мы заменим весь этот код Path2D на простой ctx.rect()
, мы увидим, что несоответствие, которое вы заметили, не связано с API Path2D:
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>
В вашем случае созданный вами шаблон будет перемещаться на 100 пикселей на оси x и y, поэтому верхний левый угол вашего offCanvas будет отображаться на уровне 100 100 пикселей, и поскольку ваш Path будет показывать только до 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>
Результаты в моем Firefox 64:
Поэтому, когда вы использовали сплошной красный цвет в качестве шаблона, эта ошибка фактически создавала полностью красную растровую карту, в то время как правильное поведение в соответствии с спецификациями - отображать прозрачные черные пиксели, где алгоритм шаблона не создавал никаких результатов.
Для исправления нам придется подождать, пока FF его предоставит.
Но учтите, что в вашем случае использование fillRect
будет 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>
translate()
чтобы нарисовать все пути. Я могу заполнить его с помощьюcreateRadialGradient()
илиcreateLinearGradient()
, но не сcreatePattern()
В этом случае , Как я могу заполнить его с помощьюcreatePattern()
Спасибо снова ты