How to transform the image pattern in JavaScript canvas fillingStyle?

早过忘川 提交于 2021-02-11 02:32:18

问题


I'm currently developing a 2D graphic library in JavaScript, and now I'm sticking with the background texture transforming problems.

I want to set the background texture (property fillStyle) of a canvas context (CanvasRenderingContext2D) to an image (CanvasPattern). It's easy to assign an image to the fillStyle. But the only problem is that, the image can't actually be translated, scaled nor skewed.

I've looked up MDN, it says there's a prototype called setTransform(). With this API you can transform the image by an SVGMatrix, that seems a little annoying. Not only you'd have to create an redundant <svg> element, it's also an experimental API, and it CAN'T work in Google Chrome.

It's just impossible to solve using a regular way. Is there any 'hacky' ways to do this?


回答1:


First draw the path then set the transform.The path stays where it was while the fill is transformed.

The example rotates the pattern inside two boxes.

const ctx = canvas.getContext('2d');
var pattern;

const img = new Image();
img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png';
img.onload = () =>  pattern = ctx.createPattern(img, 'repeat');



 requestAnimationFrame(mainLoop);
 function mainLoop(time){
     ctx.setTransform(1,0,0,1,0,0);
     ctx.clearRect(0,0,canvas.width,canvas.height);

     ctx.fillStyle = pattern;

     ctx.beginPath();
     ctx.setTransform(1,0,0,1,0,0);  
     ctx.rect(100,100,200,200); // create the path for rectangle
     ctx.setTransform(1,0,0,1,300,200);  // Set the transform for the pattern
     ctx.rotate(time / 1000);
     ctx.fill();


     ctx.beginPath();
     ctx.setTransform(1,0,0,1,0,0);
     ctx.rect(150,0,100,400); // create the path for the rectangle
     ctx.setTransform(0.2,0,0,0.2,150,200); // Set the transform for the pattern
     ctx.rotate(-time / 1000);
     ctx.fill();

     requestAnimationFrame(mainLoop);
 }
<canvas id="canvas" width="400" height="400" style="border:2px solid black;"></canvas>



回答2:


Set the transform on the CanvasRenderingContext2D, not on the CanvasPattern. This is much better supported, and you do not neet the SVGMatrix object.

The resulting painted area is the transformed one, so this might only be usefull if you want the whole canvas to have a uniform pattern.

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var img = new Image();
img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png';
img.onload = function() {
  var pattern = ctx.createPattern(img, 'repeat');
  ctx.fillStyle = pattern;
  ctx.setTransform(0.8, 0.3, 0, 0.8, 0, 0)
  ctx.fillRect(0, -172, 450, 700); //make sure the whole canvas is covered
};
<canvas id="canvas" width="400" height="400"></canvas>


来源:https://stackoverflow.com/questions/47833726/how-to-transform-the-image-pattern-in-javascript-canvas-fillingstyle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!