原文: https://zetcode.com/gfx/html5canvas/transformations/

在 HTML5 画布教程的这一部分中,我们将讨论变换。

仿射变换由零个或多个线性变换(旋转,缩放或剪切)和平移(移位)组成。 几个线性变换可以组合成一个矩阵。 旋转是使刚体绕固定点移动的变换。 缩放是一种放大或缩小对象的变换。 比例因子在所有方向上都是相同的。 平移是使每个点在指定方向上移动恒定距离的变换。 剪切是一种使对象垂直于给定轴移动的变换,该值在轴的一侧比另一侧更大。

有一种transform()方法,该方法将当前变换与该方法的参数所描述的矩阵相乘。 我们能够缩放,旋转,移动和剪切上下文。 还有执行特定变换的方法:translate()rotatescale()

平移

以下示例显示了一个简单的平移。

translation.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>HTML5 canvas translation</title>
  5. <style>
  6. canvas {border: 1px solid #bbbbbb}
  7. </style>
  8. <script>
  9. function draw() {
  10. var canvas = document.getElementById('myCanvas');
  11. var ctx = canvas.getContext('2d');
  12. ctx.fillStyle = 'gray';
  13. ctx.translate(canvas.width/2, canvas.height/2);
  14. ctx.beginPath();
  15. ctx.arc(0, 0, 30, 0, 2*Math.PI);
  16. ctx.fill();
  17. }
  18. </script>
  19. </head>
  20. <body onload="draw();">
  21. <canvas id="myCanvas" width="150" height="150">
  22. </canvas>
  23. </body>
  24. </html>

该示例在画布的中间绘制一个圆圈。

  1. ctx.translate(canvas.width/2, canvas.height/2);

translate()方法将坐标系的原点移到画布的中间。

  1. ctx.beginPath();
  2. ctx.arc(0, 0, 30, 0, 2*Math.PI);
  3. ctx.fill();

画一个圆。 它的中心点是画布的中间。

HTML5 `canvas`中的变换 - 图1

图:平移

旋转

下一个示例演示了旋转。

rotation.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>HTML5 canvas rotation</title>
  5. <script>
  6. function draw() {
  7. var canvas = document.getElementById('myCanvas');
  8. var ctx = canvas.getContext('2d');
  9. ctx.fillStyle = 'gray';
  10. ctx.rotate(Math.PI/10);
  11. ctx.fillRect(50, 10, 120, 80);
  12. }
  13. </script>
  14. </head>
  15. <body onload="draw();">
  16. <canvas id="myCanvas" width="200" height="200">
  17. </canvas>
  18. </body>
  19. </html>

该示例对矩形执行旋转。

  1. ctx.rotate(Math.PI/10);

rotate()方法执行旋转。 角度自变量表示顺时针旋转角度并以弧度表示。

HTML5 `canvas`中的变换 - 图2

图:旋转

缩放

缩放是通过scale()方法完成的。 该方法采用两个参数:x 比例因子和 y 比例因子。

scaling.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>HTML5 canvas scaling</title>
  5. <script>
  6. function draw() {
  7. var canvas = document.getElementById('myCanvas');
  8. var ctx = canvas.getContext('2d');
  9. ctx.fillStyle = 'gray';
  10. ctx.fillRect(20, 20, 80, 50);
  11. ctx.save();
  12. ctx.translate(110, 22);
  13. ctx.scale(0.5, 0.5);
  14. ctx.fillRect(0, 0, 80, 50);
  15. ctx.restore();
  16. ctx.translate(170, 20);
  17. ctx.scale(1.5, 1.5);
  18. ctx.fillRect(0, 0, 80, 50);
  19. }
  20. </script>
  21. </head>
  22. <body onload="draw();">
  23. <canvas id="myCanvas" width="300" height="200">
  24. </canvas>
  25. </body>
  26. </html>

在示例中,有一个矩形对象。 首先,我们缩小比例,然后再放大一点。

  1. ctx.save();
  2. ctx.translate(110, 22);
  3. ctx.scale(0.5, 0.5);
  4. ctx.fillRect(0, 0, 80, 50);
  5. ctx.restore();

变换操作是累加的。 为了隔离变换和缩放操作,我们将它们放在save()restore()方法之间。 save()方法保存画布的整个状态,restore()方法恢复画布的整个状态。

HTML5 `canvas`中的变换 - 图3

图:缩放

剪切

剪切是使对象的形状沿两个轴中的一个或两个变形的变换。 像缩放和平移一样,可以仅沿一个或两个坐标轴进行剪切。

shearing.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>HTML5 canvas shearing</title>
  5. <script>
  6. function draw() {
  7. var canvas = document.getElementById('myCanvas');
  8. var ctx = canvas.getContext('2d');
  9. ctx.translate(0.5, 0.5);
  10. ctx.setLineDash([2]);
  11. ctx.save();
  12. ctx.strokeStyle = 'green';
  13. ctx.strokeRect(50, 90, 160, 50);
  14. ctx.restore();
  15. ctx.save();
  16. ctx.strokeStyle = 'blue';
  17. ctx.transform(1, 1, 0, 1, 0, 0);
  18. ctx.strokeRect(50, 40, 80, 50);
  19. ctx.restore();
  20. ctx.save();
  21. ctx.strokeStyle = 'red';
  22. ctx.transform(1, 1, 0, 1, 0, -130);
  23. ctx.strokeRect(130, 10, 80, 50);
  24. ctx.restore();
  25. }
  26. </script>
  27. </head>
  28. <body onload="draw();">
  29. <canvas id="myCanvas" width="300" height="300">
  30. </canvas>
  31. </body>
  32. </html>

没有特定的剪切方法,我们使用通用的transform()方法。

  1. ctx.translate(0.5, 0.5);

这条线使矩形的线更平滑。

  1. ctx.save();
  2. ctx.strokeStyle = 'blue';
  3. ctx.transform(1, 1, 0, 1, 0, 0);
  4. ctx.strokeRect(50, 40, 80, 50);
  5. ctx.restore();

蓝色矩形被水平剪切(倾斜)。 transform()方法的参数为:水平缩放,水平剪切,垂直剪切,垂直缩放,水平平移和垂直平移。

HTML5 `canvas`中的变换 - 图4

图:抖动

甜甜圈

在下面的示例中,我们通过旋转椭圆来创建复杂的形状。

DonutEx.java

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>HTML5 canvas donut</title>
  5. <script>
  6. function draw() {
  7. var canvas = document.getElementById('myCanvas');
  8. var ctx = canvas.getContext('2d');
  9. ctx.fillStyle = 'gray';
  10. ctx.translate(0.5, 0.5);
  11. var x = canvas.width/2;
  12. var y = canvas.height/2;
  13. for (var deg = 0; deg < 360; deg += 5) {
  14. var rad = deg * Math.PI / 180;
  15. ctx.beginPath();
  16. ctx.ellipse(x, y, 30, 130, rad, 0, 2*Math.PI);
  17. ctx.stroke();
  18. }
  19. }
  20. </script>
  21. </head>
  22. <body onload="draw();">
  23. <canvas id="myCanvas" width="300" height="300">
  24. </canvas>
  25. </body>
  26. </html>

该示例使用ellipse()方法,在撰写本教程时,并非所有浏览器都支持该方法。 该示例在 Chrome 和 Opera 上运行。

  1. var x = canvas.width/2;
  2. var y = canvas.height/2;

椭圆的中心位于画布的中心。

  1. for (var deg = 0; deg < 360; deg += 5) {
  2. var rad = deg * Math.PI / 180;
  3. ctx.beginPath();
  4. ctx.ellipse(x, y, 30, 130, rad, 0, 2*Math.PI);
  5. ctx.stroke();
  6. }

我们创建 36 个椭圆。 椭圆旋转。 ellipse()方法采用以下参数:椭圆中心点的 x 和 y 坐标,椭圆的长轴半径,椭圆的短轴半径,旋转,起始角度和终止角度。

在 Java 2D 教程的这一部分中,我们讨论了变换。