HTML5 Canvas 教程:九、变换

九、变换 Transformations

 

译者注:变换计算中需要用到很多矩阵变换运算,如果不熟悉矩阵变换运算,那么理解以下代码会有一定困难,建议先熟悉矩阵变换运算再阅读以下内容。这里有一篇很好的文章详细解释了矩阵运算:浅谈矩阵变换——Matrix

 

9.1平移 Translate

 

为了在HTML5画布上实现平移,可以使用上下文对象的translate()方法。平移是一种移动整个画布的方法。例如,有一个在画布上绘制复杂图形的函数,并且需要平移图形,那么平移上下文要比调整组成图形的所有点的x和y位置容易得多。

 

平移首先通过变换画布上下文,然后再绘制图形。在本教程中,将平移画布上下文,然后在位置(0, 0)绘制矩形。由于画布上下文被平移,矩形也将被平移。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="myCanvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('myCanvas');

      var context = canvas.getContext('2d');

      var rectWidth = 150;

      var rectHeight = 75;

 

      // translate context to center of canvas

      context.translate(canvas.width / 2, canvas.height / 2);

      context.fillStyle = 'blue';

      context.fillRect(rectWidth / -2, rectHeight / -2, rectWidth, rectHeight);

    </script>

  </body>

</html>

 

以上代码演示了在画布上平移一个矩形到居中位置。

 

9.2缩放变换 Scale Transform

 

要缩放HTML5画布,可以使用scale()方法,此方法可缩放画布的X和Y两个方向。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="myCanvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('myCanvas');

      var context = canvas.getContext('2d');

      var rectWidth = 150;

      var rectHeight = 75;

 

      // translate context to center of canvas

      context.translate(canvas.width / 2, canvas.height / 2);

 

      // scale y component

      context.scale(10.5);

 

      context.fillStyle = 'blue';

      context.fillRect(rectWidth / -2, rectHeight / -2, rectWidth, rectHeight);

    </script>

  </body>

</html>

 

以上代码演示了在画布上绘制一个矩形,并在Y方向缩放0.5倍。

 

 

9.3旋转变换 Rotate Transform

 

要旋转HTML5画布,可以使用rotate()转换方法。旋转变换需要提供转过的弧度(注意不是角度)。为了定义旋转点,需要首先平移画布上下文对象,以便上下文的左上角位于所需的旋转点上。在本教程中,平移了画布上下文,使得上下文的左上角直接位于矩形的中心,从而产生围绕矩形中心的旋转。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="myCanvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('myCanvas');

      var context = canvas.getContext('2d');

      var rectWidth = 150;

      var rectHeight = 75;

 

      // translate context to center of canvas

      context.translate(canvas.width / 2, canvas.height / 2);

 

      // rotate 45 degrees clockwise

      context.rotate(Math.PI / 4);

 

      context.fillStyle = 'blue';

      context.fillRect(rectWidth / -2, rectHeight / -2, rectWidth, rectHeight);

    </script>

  </body>

</html>

 

以上代码演示了平移画布,绘制矩形,并将其旋转一定角度。

 

 

9.4自定义变换 Custom Transform

 

为了将自定义转换矩阵应用到HTML5画布,可以使用transform()方法。根据以下约定,该方法需要3×3矩阵的六个分量:

 

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="myCanvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('myCanvas');

      var context = canvas.getContext('2d');

      var rectWidth = 150;

      var rectHeight = 75;

 

      // translation matrix:

      //  1  0  tx

      //  0  1  ty

      //  0  0  1

      var tx = canvas.width / 2;

      var ty = canvas.height / 2;

      // apply custom transform

      context.transform(1001, tx, ty);

      context.fillStyle = 'blue';

      context.fillRect(rectWidth / -2, rectHeight / -2, rectWidth, rectHeight);

    </script>

  </body>

</html>

 

以上代码演示了自定义变换。

 

9.5斜切变换 Shear Transform

 

为了在HTML5画布上实现斜切变换,可以使用transform()方法进行矩阵转换。SX定义水平方向切变,SY定义垂直方向的切变。

 

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="myCanvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('myCanvas');

      var context = canvas.getContext('2d');

      var rectWidth = 150;

      var rectHeight = 75;

 

      // shear matrix:

      //  1  sx  0

      //  sy  1  0

      //  0  0  1

 

      var sx = 0.75;

      // .75 horizontal shear

      var sy = 0;

      // no vertical shear

 

      // translate context to center of canvas

      context.translate(canvas.width / 2, canvas.height / 2);

 

      // apply custom transform

      context.transform(1, sy, sx, 100);

 

      context.fillStyle = 'blue';

      context.fillRect(-rectWidth / 2, rectHeight / -2, rectWidth, rectHeight);

    </script>

  </body>

</html>

 

以上代码演示了在画布上绘制一个蓝色矩形,并进行X方向的斜切变换。

 

 

9.6镜像变换 Mirror Transform

 

要使用HTML5 Canvas创建镜像变换,我们可以在上下文对象的x方向上应用负比例来水平翻转,或者可以在上下文对象的y方向上应用负比例来垂直翻转。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="myCanvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('myCanvas');

      var context = canvas.getContext('2d');

 

      // translate context to center of canvas

      context.translate(canvas.width / 2, canvas.height / 2);

 

      // flip context horizontally

      context.scale(-11);

 

      context.font = '30pt Calibri';

      context.textAlign = 'center';

      context.fillStyle = 'blue';

      context.fillText('Hello World!'00);

    </script>

  </body>

</html>

 

以上代码演示了在画布的X方向反转一段文字。

 

 

9.7重置变换 Reset Transform

 

为了重置HTML5 Canvas矩阵变换,可以使用setTransform()方法执行以下矩阵变换,将转换矩阵设置为其默认状态:

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="myCanvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('myCanvas');

      var context = canvas.getContext('2d');

      var rectWidth = 150;

      var rectHeight = 75;

 

      // translate context to center of canvas

      context.translate(canvas.width / 2, canvas.height / 2);

 

      context.fillStyle = 'blue';

      context.fillRect(-rectWidth / 2, rectHeight / -2, rectWidth, rectHeight);

 

      // Reset Transform

      // 1 0 0

      // 0 1 0

      // 0 0 1

 

      // apply custom transform

      context.setTransform(100100);

 

      context.fillStyle = 'red';

      context.fillRect(00, rectWidth, rectHeight);

    </script>

  </body>

</html>

 

以上代码演示了在画布上重置变换,并用红色绘制默认状态的图形。

 

 

9.8状态栈变换 Transformation State Stack

 

为了用HTML5 Canvas保存和恢复不同的变换状态,可以使用canvas上下文对象的save()和restore()方法。

 

在本教程中,将通过在每次转换之前将状态推入状态堆栈来保存变换状态,也就是为上下文对象设置保存点,以便上下文能准确回复到保存点的状态。首先绘制一个蓝色矩形,恢复并弹出最后一个转换状态;再绘制一个红色矩形,恢复并弹出最后一个转换状态;再绘制一个黄色矩形,最后恢复并弹出最终转换状态;再绘制一个绿色矩形。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="myCanvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('myCanvas');

      var context = canvas.getContext('2d');

      var rectWidth = 150;

      var rectHeight = 75;

 

      context.save();

      // save state 1

      context.translate(canvas.width / 2, canvas.height / 2);

 

      context.save();

      // save state 2

      context.rotate(Math.PI / 4);

 

      context.save();

      // save state 3

      context.scale(22);

 

      context.fillStyle = 'blue';

      context.fillRect(rectWidth / -2, rectHeight / -2, rectWidth, rectHeight);

 

      context.restore();

      // restore state 3

      context.fillStyle = 'red';

      context.fillRect(rectWidth / -2, rectHeight / -2, rectWidth, rectHeight);

 

      context.restore();

      // restore state 2

      context.fillStyle = 'yellow';

      context.fillRect(rectWidth / -2, rectHeight / -2, rectWidth, rectHeight);

 

      context.restore();

      // restore state 1

      context.fillStyle = 'green';

      context.fillRect(rectWidth / -2, rectHeight / -2, rectWidth, rectHeight);

    </script>

  </body>

</html>

 

以上代码演示了在画布上保存和弹出状态变换。

 

 

9.9椭圆 Oval

 

要使用HTML5 Canvas创建一个椭圆形,可以为上下文状态设置一个保存点,然后水平拉伸画布上下文,画一个圆圈,然后再恢复画布到保存点的状态,最后应用样式。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="myCanvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('myCanvas');

      var context = canvas.getContext('2d');

      var centerX = 0;

      var centerY = 0;

      var radius = 50;

 

      // save state

      context.save();

 

      // translate context

      context.translate(canvas.width / 2, canvas.height / 2);

 

      // scale context horizontally

      context.scale(21);

 

      // draw circle which will be stretched into an oval

      context.beginPath();

      context.arc(centerX, centerY, radius, 02 * Math.PI, false);

 

      // restore to original state

      context.restore();

 

      // apply styling

      context.fillStyle = '#8ED6FF';

      context.fill();

      context.lineWidth = 5;

      context.strokeStyle = 'black';

      context.stroke();

    </script>

  </body>

</html>

 

以上代码演示了在画布上设置保存点,然后使画布在X方向放大2倍,再绘制一个圆(由于受到X方向放大两倍的影响,这个圆变成了椭圆),然后恢复到保存点并应用样式,最后为椭圆描边的过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值