变换矩阵
之前三节所说的坐标变换的三种方式——平移translate(),缩放scale(),以及旋转rotate()都可以通过transform()做到。
在介绍矩阵变换transform()前,我们来说一说什么是变换矩阵。
变换矩阵
以上是Canvas中transform()方法所对应的变换矩阵。而此方法正是传入图中所示的六个参数,具体为context.transform(a,b,c,d,e,f)。
各参数意义对应如下表:
参数 意义
a 水平缩放(1)
b 水平倾斜(0)
c 垂直倾斜(0)
d 垂直缩放(1)
e 水平位移(0)
f 垂直位移(0)
当我们把对应的0或1代入进矩阵,可以发现这是一个单位矩阵(水平和垂直缩放默认值是1,代表缩放1倍,即不缩放)。该方法使用一个新的变化矩阵与当前变换矩阵进行乘法运算,然后得到各种变化的效果。
这里简单说一下,当我们想对一个图形进行变换的时候,只要对变换矩阵相应的参数进行操作,操作之后,对图形的各个定点的坐标分别乘以这个矩阵,就能得到新的定点的坐标。
而Canvas绘图中,就给咱们提供了一个函数来改变这个变换矩阵,那就是transform()。
矩阵变换transform()注:以下三个变换的转换结论转自张雯的博客,童鞋们可以戳进去看看详情。
平移变换
平移变换
如上图所示:
x’ = x + dx,
y’ = y + dy。
也即是说可以使用
context.transform (1,0,0,1,dx,dy)代替context.translate(dx,dy)。
也可以使用
context.transform(0,1,1,0,dx,dy)代替。
同理可以使用
context.transform(sx,0,0,sy,0,0)代替context.scale(sx, sy);
也可以使用context.transform(0,sy,sx,0,0,0);
旋转变换
旋转变换
如上图图所示:
B点是通过A点逆时针旋转θ得到,
x = r * cosa,
y = r * sina
即
x’=r*cos(a+θ)=x*cosθ-y*sinθ,
y’=r*sin(a+θ)=x*sinθ+y*cosθ
也即是
变换矩阵
综上:
context.transform(Math.cos(θ*Math.PI/180),Math.sin(θ*Math.PI/180),
-Math.sin(θ*Math.PI/180),Math.cos(θ*Math.PI/180),0,0)可以替代context.rotate(θ)。
也可以使用
context.transform(-Math.sin(θ*Math.PI/180),Math.cos(θ*Math.PI/180),
Math.cos(θ*Math.PI/180),Math.sin(θ*Math.PI/180),0,0)替代。
以上结论引自张雯的博客,很好的说明了矩阵变换的过程,但是结论过于复杂,建议使用transform()的时候,可以在如下几个情况下使用:
不用再使用它去实现旋转了,另外也没有也不用全记这些结论,直接记下abcdef六个参数的意义,效果是一样的。
下面我们看一个代码,熟悉一下:
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>矩阵变换</title> <style> body { background: url("./images/bg3.jpg") repeat; } #canvas { border: 1px solid #aaaaaa; display: block; margin: 50px auto; } </style> </head> <body> <div> <canvas> 你的浏览器居然不支持Canvas?!赶快换一个吧!! </canvas> </div> <script> window.onload = function(){ var canvas = document.getElementById("canvas"); canvas.width = 800; canvas.height = 600; var context = canvas.getContext("2d"); context.fillStyle = "#FFF"; context.fillRect(0,0,800,600); context.fillStyle = "yellow"; context.strokeStyle = "#00AAAA"; context.lineWidth = 5; context.save(); //平移至(300,200) context.transform(1,0,0,1,300,200); //水平方向放大2倍,垂直方向放大1.5倍 context.transform(2,0,0,1.5,0,0); //水平方向向右倾斜宽度10%的距离,垂直方向向上倾斜高度10%的距离 context.transform(1,-0.1,0.1,1,0,0); context.fillRect(0,0,200,200); context.strokeRect(0,0,200,200); context.restore(); }; </script> </body> </html>演示 16-1
运行结果:
transform
setTransform()方法