浅谈canvas的相对变换、绝对变换

71 阅读2分钟

源码:github.com/huohuo-fei/…

我们知道:canvas有位移、旋转、缩放画布的功能。同时,也提供了transform()setTransform()两个变换方法,用矩阵的形式表示所有的变换。那这两个方法有什么区别呢?MDN上对二者的解释是:

  • Canvas 2D API 的CanvasRenderingContext2D.transform() 方法用于将由该方法的参数所描述的矩阵与当前的变换相乘。你可以缩放、旋转、平移和倾斜上下文
  • CanvasRenderingContext2D.setTransform() 方法用于使用单位矩阵重新设置(覆盖)当前的变换并调用变换,此变换由方法的变量进行描述。这使你能够对上下文进行缩放、旋转、平移(移动)和倾斜操作。

从官方的解释上可以看到transform是基于当前的变换而进行的,setTransform则是重置了当前的变换。文字有些抽象,我们可以尝试运行几个例子:

Snipaste_2024-10-06_10-40-57.png

/** transform **/
// 三个矩形
ctx.fillStyle = 'rgba(200,200,200,1)';
ctx.fillRect(0, 0, canvasRef1.value.width, canvasRef1.value.height);
ctx.fillStyle = 'rgba(100,100,100,1)';
ctx.transform(1, 0, 0, 1, 50, 50);
ctx.fillRect(0, 0, 50, 50);

ctx.fillStyle = 'rgba(100,100,100,0.6)';
ctx.transform(1, 0, 0, 1, 50, 50);
ctx.fillRect(0, 0, 50, 50);

ctx.save();
ctx.fillStyle = 'rgba(100,100,100,0.3)';
ctx.transform(1, 0, 0, 1, 50, 50);
ctx.fillRect(0, 0, 50, 50);
ctx.restore();

/** setTransform **/
ctx.fillStyle = 'rgba(200,200,200,1)';
ctx.fillRect(0, 0, canvasRef2.value.width, canvasRef2.value.height);
ctx.fillStyle = 'rgba(100,100,100,1)';
ctx.setTransform(1, 0, 0, 1, 50, 50);
ctx.fillRect(0, 0, 50, 50);
ctx.fillStyle = 'rgba(255,255,2,0.6)';

ctx.setTransform(1, 0, 0, 1, 50, 50);
ctx.fillRect(0, 0, 70, 70);
ctx.fillStyle = 'rgba(100,100,100,0.3)';

ctx.setTransform(1, 0, 0, 1, 100, 100);
ctx.fillRect(0, 0, 50, 50);

我们可以看到,transform每次变换,都是参考当前的坐标系,或者说矩阵进行的。第一个正方形向右下偏移50px绘制,此时相对的是左上角的canvas原点。第二个进行相同的变换,但此时的基点,是变换后的基点,也就是第一个也就是官方说的当前变换的基础上进行的变换。

setTransform绘制出的三个正方形,三次的变换基点都是左上角的canvas原点。 总的来说transform是相对当前变换的变换,也就是相对变换,首次执行的变换,可以理解为当前变换的矩阵为三阶单位矩阵。setTransform则是绝对变换,永远都相对于画布的原点进行变换。