Ch16 矩阵变换

    在介绍矩阵变换transform()前,我们来说一说什么是变换矩阵。

    以上是Canvas中transform()方法所对应的变换矩阵。而此方法正是传入图中所示的六个参数,具体为context.transform(a,b,c,d,e,f)

    各参数意义对应如下表:

    当我们把对应的0或1代入进矩阵,可以发现这是一个单位矩阵(水平和垂直缩放默认值是1,代表缩放1倍,即不缩放)。该方法使用一个新的变化矩阵与当前变换矩阵进行乘法运算,然后得到各种变化的效果。

    这里简单说一下,当我们想对一个图形进行变换的时候,只要对变换矩阵相应的参数进行操作,操作之后,对图形的各个定点的坐标分别乘以这个矩阵,就能得到新的定点的坐标。

    而Canvas绘图中,就给咱们提供了一个函数来改变这个变换矩阵,那就是transform()

    平移变换

    如上图所示: x’ = x + dxy’ = y + 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 * cosay = 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()的时候,可以在如下几个情况下使用:

    1. 使用context.transform (1,0,0,1,dx,dy)代替
    2. 使用context.transform(sx,0,0,sy,0,0)代替context.scale(sx, sy)
    3. 使用context.transform(0,b,c,0,0,0)来实现倾斜效果(最实用)。

    不用再使用它去实现旋转了,另外也没有也不用全记这些结论,直接记下abcdef六个参数的意义,效果是一样的。

    演示 16-1

    运行结果:

    transform()方法的行为相对于由 rotate(),scale(), translate(), or transform() 完成的其他变换。例如:如果我们已经将绘图设置为放到两倍,则 transform() 方法会把绘图放大两倍,那么我们的绘图最终将放大四倍。这一点和之前的变换是一样的。

    但是setTransform()不会相对于其他变换来发生行为。它的参数也是六个,context.setTransform(a,b,c,d,e,f),与transform()一样。

    这里我们通过一个例子来说明: 绘制一个矩形,通过 setTransform() 重置并创建新的变换矩阵,再次绘制矩形,重置并创建新的变换矩阵,然后再次绘制矩形。

    1. <!DOCTYPE html>
    2. <html lang="zh">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>矩阵变换</title>
    6. <style>
    7. #canvas { border: 1px solid #aaaaaa; display: block; margin: 50px auto; }
    8. </style>
    9. </head>
    10. <body>
    11. <div id="canvas-warp">
    12. <canvas id="canvas">
    13. </canvas>
    14. </div>
    15. <script>
    16. window.onload = function(){
    17. var canvas = document.getElementById("canvas");
    18. canvas.width = 800;
    19. canvas.height = 600;
    20. context.fillStyle = "#FFF";
    21. context.fillRect(0,0,800,600);
    22. context.fillStyle="yellow";
    23. context.fillRect(200,100,250,100)
    24. context.setTransform(1,0.5,-0.5,1,30,10);
    25. context.fillStyle="red";
    26. context.fillRect(200,100,250,100);
    27. context.setTransform(1,0.5,-0.5,1,30,10);
    28. context.fillStyle="blue";
    29. context.fillRect(200,100,250,100);
    30. };
    31. </script>
    32. </html>

    运行结果:

    setTransform

    解释一下过程:每当我们调用 setTransform() 时,它都会重置前一个变换矩阵然后构建新的矩阵,因此在下面的例子中,不会显示红色矩形,因为它在蓝色矩形下面。