HTML5 Canvas 教程:十二、动画

本文详细介绍了如何使用HTML5 Canvas创建各种动画效果,包括清除画布、动画帧、线性运动、加速度、振荡动画及动画的启动与停止。通过具体代码示例,展示了动画原理及其实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

十二、动画 Animation

 

12.1清除画布内容 Clear Canvas

 

为了清除HTML5画布,可以使用clearRect()方法来清除画布位图。该方法的性能比清除画布的其他技术要好得多,比如重置画布的宽度和高度,或者销毁画布元素然后重新创建它。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

      #buttons {

        position: absolute;

        top: 5px;

        left: 10px;

      }

      #buttons > input {

        padding: 10px;

        display: block;

        margin-top: 5px;

      }

    </style>

  </head>

  <body>

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

    <div id="buttons">

      <input type="button" id="clear" value="Clear">

    </div>

    <script>

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

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

 

      // begin custom shape

      context.beginPath();

      context.moveTo(17080);

      context.bezierCurveTo(130100130150230150);

      context.bezierCurveTo(250180320180340150);

      context.bezierCurveTo(420150420120390100);

      context.bezierCurveTo(430403703034050);

      context.bezierCurveTo(32052502025050);

      context.bezierCurveTo(20051502017080);

 

      // complete custom shape

      context.closePath();

      context.lineWidth = 5;

      context.strokeStyle = 'blue';

      context.stroke();

 

      // bind event handler to clear button

      document.getElementById('clear').addEventListener('click'function() {

        context.clearRect(00, canvas.width, canvas.height);

      }, false);

 

    </script>

  </body>

</html>

 

代码说明:点击清除按钮清除画布。

 

以上代码演示了点击清除按钮,清除画布上的所有内容。

 

 

12.2动画帧 Animation Frame

 

要使用HTML5 Canvas创建动画,可以使用requestAnimFrame shim,它使浏览器能够确定动画的最佳FPS。对于每个动画帧,我们可以更新画布上的元素,清除画布,重新绘制画布,然后继续请求另一个动画帧。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

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

    <script>

      window.requestAnimFrame = (function(callback) {

        return window.requestAnimationFrame || 

               window.webkitRequestAnimationFrame || 

               window.mozRequestAnimationFrame || 

               window.oRequestAnimationFrame || 

               window.msRequestAnimationFrame ||

        function(callback) {

          window.setTimeout(callback1000 / 60);

        };

      })();

 

      function drawRectangle(myRectanglecontext) {

        context.beginPath();

        context.rect(myRectangle.x, myRectangle.y, 

                    myRectangle.width, myRectangle.height);

        context.fillStyle = '#8ED6FF';

        context.fill();

        context.lineWidth = myRectangle.borderWidth;

        context.strokeStyle = 'black';

        context.stroke();

      }

 

      function animate(myRectanglecanvascontextstartTime) {

        // update

        var time = (new Date()).getTime() - startTime;

 

        var linearSpeed = 100;

        // pixels / second

        var newX = linearSpeed * time / 1000;

 

        if(newX < canvas.width-myRectangle.width-myRectangle.borderWidth/2) {

          myRectangle.x = newX;

        }

 

        // clear

        context.clearRect(00canvas.width, canvas.height);

 

        drawRectangle(myRectanglecontext);

 

        // request new frame

        requestAnimFrame(function() {

          animate(myRectanglecanvascontextstartTime);

        });

      }

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

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

 

      var myRectangle = {

        x: 0,

        y: 75,

        width: 100,

        height: 50,

        borderWidth: 5

      };

 

      drawRectangle(myRectangle, context);

 

      // wait one second before starting animation

      setTimeout(function() {

        var startTime = (new Date()).getTime();

        animate(myRectangle, canvas, context, startTime);

      }, 1000);

    </script>

  </body>

</html>

 

以上代码演示了在画布上绘制一个矩形,并使矩形向右移动的动画。注意代码中的animate方法,该方法不断更新矩形的位置,并清除画布,将新的矩形绘制出来以实现矩形的移动。

 

12.3线性运动 Linear Motion

 

为了用HTML5画布创建线性运动动画,我们可以根据速度方程增加每个帧对象的x、y值以改变对象的位置,计算方式为:距离=速度*时间(distance = velocity * time)。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

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

    <script>

      window.requestAnimFrame = (function(callback) {

        return window.requestAnimationFrame || 

               window.webkitRequestAnimationFrame || 

               window.mozRequestAnimationFrame || 

               window.oRequestAnimationFrame || 

               window.msRequestAnimationFrame ||

        function(callback) {

          window.setTimeout(callback1000 / 60);

        };

      })();

 

      function drawRectangle(myRectanglecontext) {

        context.beginPath();

        context.rect(myRectangle.x, myRectangle.y, myRectangle.width, myRectangle.height);

        context.fillStyle = '#8ED6FF';

        context.fill();

        context.lineWidth = myRectangle.borderWidth;

        context.strokeStyle = 'black';

        context.stroke();

      }

 

      function animate(myRectanglecanvascontextstartTime) {

        // update

        var time = (new Date()).getTime() - startTime;

 

        var linearSpeed = 100;

        // pixels / second

        var newX = linearSpeed * time / 1000;

 

        if(newX < canvas.width-myRectangle.width-myRectangle.borderWidth/2) {

          myRectangle.x = newX;

        }

 

        // clear

        context.clearRect(00canvas.width, canvas.height);

 

        drawRectangle(myRectanglecontext);

 

        // request new frame

        requestAnimFrame(function() {

          animate(myRectanglecanvascontextstartTime);

        });

      }

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

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

 

      var myRectangle = {

        x: 0,

        y: 75,

        width: 100,

        height: 50,

        borderWidth: 5

      };

 

      drawRectangle(myRectangle, context);

 

      // wait one second before starting animation

      setTimeout(function() {

        var startTime = (new Date()).getTime();

        animate(myRectangle, canvas, context, startTime);

      }, 1000);

    </script>

  </body>

</html>

 

这段代码的演示内容与上一段基本一致,不在赘述。

 

 

12.4加速度 Acceleration

 

为了用HTML5画布创建二次运动动画,我们可以为每帧增加对象的vx(水平速度)、vy(垂直速度)或vx和vy两者同时增加,然后根据加速度方程更新对象的位置,计算方法为:距离=速度*时间+ 1/2 *加速度*时间^2(distance = velocity * time + 1/2 * acceleration * time^2)。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

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

    <script>

      window.requestAnimFrame = (function(callback) {

        return window.requestAnimationFrame || 

               window.webkitRequestAnimationFrame || 

               window.mozRequestAnimationFrame || 

               window.oRequestAnimationFrame || 

               window.msRequestAnimationFrame ||

        function(callback) {

          window.setTimeout(callback1000 / 60);

        };

      })();

 

      function drawRectangle(myRectanglecontext) {

        context.beginPath();

        context.rect(myRectangle.x, myRectangle.y, myRectangle.width, myRectangle.height);

        context.fillStyle = '#8ED6FF';

        context.fill();

        context.lineWidth = myRectangle.borderWidth;

        context.strokeStyle = 'black';

        context.stroke();

      }

 

      function animate(myRectanglecanvascontextstartTime) {

        // update

        var time = (new Date()).getTime() - startTime;

 

        // pixels / second^2

        var gravity = 200;

 

        myRectangle.y = 0.5 * gravity * Math.pow(time / 10002);

 

        if(myRectangle.y > canvas.height - 

                myRectangle.height - myRectangle.borderWidth / 2) {

          myRectangle.y = canvas.height - 

                myRectangle.height - myRectangle.borderWidth / 2;

        }

        lastTime = time;

 

        // clear

        context.clearRect(00canvas.width, canvas.height);

 

        // draw

        drawRectangle(myRectanglecontext);

 

        // request new frame

        requestAnimFrame(function() {

          animate(myRectanglecanvascontextstartTime);

        });

      }

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

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

 

      var myRectangle = {

        x: 239,

        y: 0,

        width: 100,

        height: 50,

        borderWidth: 5

      };

 

      drawRectangle(myRectangle, context);

 

      // wait one second before dropping rectangle

      setTimeout(function() {

        var startTime = (new Date()).getTime();

        animate(myRectangle, canvas, context, startTime);

      }, 2000);

 

    </script>

  </body>

</html>

 

以上代码演示了在画布上创建一个垂直降落的矩形,并且在降落过程中有一定的加速度,请注意代码中与加速度有关的几项常量,可以试着将其改为更符合实际的重力加速度。

 

 

12.5振荡(往复)动画 Oscillation Animation

 

为了使用HTML5画布创建振荡往复动画,我们可以使用简单的谐波振荡方程来设置图形在每个帧的位置:

x(t) = 幅值*sin(t * 2PI/周期) + x0,(x(t) = amplitude * sin(t * 2PI / period) + x0)。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

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

    <script>

      window.requestAnimFrame = (function(callback) {

        return window.requestAnimationFrame || 

               window.webkitRequestAnimationFrame || 

               window.mozRequestAnimationFrame || 

               window.oRequestAnimationFrame || 

               window.msRequestAnimationFrame ||

        function(callback) {

          window.setTimeout(callback1000 / 60);

        };

      })();

 

      function drawRectangle(myRectanglecontext) {

        context.beginPath();

        context.rect(myRectangle.x, myRectangle.y, 

                        myRectangle.width, myRectangle.height);

        context.fillStyle = '#8ED6FF';

        context.fill();

        context.lineWidth = myRectangle.borderWidth;

        context.strokeStyle = 'black';

        context.stroke();

      }

 

      function animate(myRectanglecanvascontextstartTime) {

        // update

        var time = (new Date()).getTime() - startTime;

        var amplitude = 150;

 

        // in ms

        var period = 2000;

        var centerX = canvas.width / 2 - myRectangle.width / 2;

        var nextX = amplitude * Math.sin(time * 2 * Math.PI / period) + 

                      centerX;

        myRectangle.x = nextX;

 

        // clear

        context.clearRect(00canvas.width, canvas.height);

 

        // draw

        drawRectangle(myRectanglecontext);

 

        // request new frame

        requestAnimFrame(function() {

          animate(myRectanglecanvascontextstartTime);

        });

      }

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

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

 

      var myRectangle = {

        x: 250,

        y: 70,

        width: 100,

        height: 50,

        borderWidth: 5

      };

 

      drawRectangle(myRectangle, context);

 

      // wait one second before starting animation

      setTimeout(function() {

        var startTime = (new Date()).getTime();

        animate(myRectangle, canvas, context, startTime);

      }, 1000);

    </script>

  </body>

</html>

 

以上代码演示了在画布上绘制一个矩形,并使矩形进行振荡往复运动。

 

 

12.6动画的启动与停止 Start and Stop an Animation

 

要启动HTML5画布动画,可以不断地请求新的动画帧;要停止HTML5画布动画,则停止请求新的动画帧。

 

<!DOCTYPE HTML>

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

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

    <script>

      window.requestAnimFrame = (function(callback) {

        return window.requestAnimationFrame || 

               window.webkitRequestAnimationFrame || 

               window.mozRequestAnimationFrame || 

               window.oRequestAnimationFrame || 

               window.msRequestAnimationFrame ||

        function(callback) {

          window.setTimeout(callback1000 / 60);

        };

      })();

 

      function drawRect(myRectanglecontext) {

        context.beginPath();

        context.rect(myRectangle.x, myRectangle.y, 

                        myRectangle.width, myRectangle.height);

        context.fillStyle = '#8ED6FF';

        context.fill();

        context.lineWidth = myRectangle.borderWidth;

        context.strokeStyle = 'black';

        context.stroke();

      }

 

      function animate(lastTimemyRectanglerunAnimationcanvascontext) {

        if(runAnimation.value) {

          // update

          var time = (new Date()).getTime();

          var timeDiff = time - lastTime;

 

          // pixels / second

          var linearSpeed = 100;

          var linearDistEachFrame = linearSpeed * timeDiff / 1000;

          var currentX = myRectangle.x;

 

          if(currentX < canvas.width - 

                           myRectangle.width - myRectangle.borderWidth / 2) {

            var newX = currentX + linearDistEachFrame;

            myRectangle.x = newX;

          }

 

          // clear

          context.clearRect(00canvas.width, canvas.height);

 

          // draw

          drawRect(myRectanglecontext);

 

          // request new frame

          requestAnimFrame(function() {

            animate(timemyRectanglerunAnimationcanvascontext);

          });

        }

      }

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

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

 

      var myRectangle = {

        x: 0,

        y: 75,

        width: 100,

        height: 50,

        borderWidth: 5

      };

 

      /*

       * define the runAnimation boolean as an obect

       * so that it can be modified by reference

       */

      var runAnimation = {

        value: false

      };

 

      // add click listener to canvas

      document.getElementById('myCanvas')

                .addEventListener('click'function() {

        // flip flag

        runAnimation.value = !runAnimation.value;

 

        if(runAnimation.value) {

          var date = new Date();

          var time = date.getTime();

          animate(time, myRectangle, runAnimation, canvas, context);

        }

      });

      drawRect(myRectangle, context);

    </script>

  </body>

</html>

 

说明:点击画布启动动画并停止动画。

 

以上代码演示了通过点击鼠标启动和停止动画,而不是像以上的代码范例停止1秒后启动动画。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值