Reputation: 1128
Currently drawing this onto a canvas:
I want to use a texture that repeats only on the Y axis where the red rectangle is.
However, when drawing the texture, nothing shows up when repeat-y
is specified. It works when the repeat value is repeat
however.
ctx.fillStyle = ctx.createPattern(assets.grassRightTexture, 'repeat-y');
ctx.fillRect(dimensions.left + dimensions.width, dimensions.top, 5, dimensions.height);
The assets.grassRightTexture
is a preloaded img element with a 4px by 32px sprite.
Not sure if im doing something wrong but I didnt notice anything when reading the moz canvas docs.
Thank you.
Upvotes: 1
Views: 138
Reputation: 136627
The CanvasPattern
object is always relative to the context's current transformation matrix (CTM) and not to the shape where you expect it to be drawn.
So here, since you do create your pattern from an <img>
element that has its width
set to 4px, your CanvasPattern
instance will cover only the rectangle from the coordinates (0, -∞) to (4, ∞).
Since the rectangle your draw doesn't cover this area, you're filling with transparent pixels.
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
// prepare the CanvasPattern
canvas.width = 4;
canvas.height = 32;
ctx.fillStyle = "red";
ctx.fillRect(0, 0, canvas.width, canvas.height);
const pattern = ctx.createPattern(canvas, "repeat-y");
// try to use the pattern
canvas.width = 300;
canvas.height = 150;
ctx.fillStyle = pattern;
ctx.fillRect(24, 50, 50, 50); // doesn't draw anything
ctx.strokeRect(24, 50, 50, 50); // to show we did draw something
setTimeout(() => {
ctx.fillRect(0, 75, 50, 50); // doesn't draw anything
ctx.strokeRect(0, 75, 50, 50); // to show we did draw something
}, 1000);
<canvas></canvas>
To overcome this you can either transform your CanvasPattern
object thanks to its setTransform()
method,
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
// prepare the CanvasPattern
canvas.width = 4;
canvas.height = 32;
ctx.fillStyle = "red";
ctx.fillRect(0, 0, canvas.width, canvas.height);
const pattern = ctx.createPattern(canvas, "repeat-y");
// try to use the pattern
canvas.width = 300;
canvas.height = 150;
ctx.fillStyle = pattern;
// we translate the CanvasPattern so that our shape is covered
// setTransform accepts a DOMMatrixInit dictionary
// `e` represents the x-axis translate
pattern.setTransform({e: 24});
ctx.fillRect(24, 50, 50, 50);
ctx.strokeRect(24, 50, 50, 50);
<canvas></canvas>
or you can draw on your context in two steps with 2 different CTM for tracing the shape and for painting it.
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
// prepare the CanvasPattern
canvas.width = 4;
canvas.height = 32;
ctx.fillStyle = "red";
ctx.fillRect(0, 0, canvas.width, canvas.height);
const pattern = ctx.createPattern(canvas, "repeat-y");
// try to use the pattern
canvas.width = 300;
canvas.height = 150;
ctx.fillStyle = pattern;
// we trace at identity CTM
ctx.rect(24, 50, 50, 50);
// we move only the fillStyle & strokeStyle
ctx.translate(24, 0);
ctx.fill();
ctx.stroke();
<canvas></canvas>
Though there is a bug in Firefox that makes this second option fail there.
Upvotes: 2