当前位置: 代码网 > it编程>网页制作>Css > 可视化系列讲解:canvas的动画实现

可视化系列讲解:canvas的动画实现

2024年08月01日 Css 我要评论
前端可视化系列讲解:css3D,svg,canvas等


一、canvas动画

1.1 canvas绘图都是通过javascript 去操控的,如要实现一些交互性动画是相当容易的。那canvas是如何做一些基本动画的?

◼ canvas可能最大的限制就是图像一旦绘制出来,它就是一直保持那样了。
◼ 如需要执行动画,不得不对画布上所有图形进行一帧一帧的重绘(比如在1秒绘60帧就可绘出流畅的动画了)。
◼ 为了实现动画,我们需要一些可以定时执行重绘的方法。然而在canvas中有三种方法可以实现:分别为 setinterval 、 settimeout 和 requestanimationframe 三种方法来定期执行指定函数进行重绘。

1.2 canvas 画出一帧动画的基本步骤(如要画出流畅动画,1s 需绘60帧):

◼ 第一步:用 clearrect 方法清空 canvas ,除非接下来要画的内容会完全充满 canvas(例如背景图),否则你需要清空所有。
◼ 第二步:保存 canvas 状态,如果加了 canvas 状态的设置(样式,变形之类的),又想在每画一帧之时都是原始状态的话,
你需要先保存一下。
◼ 第三步:绘制动画图形(animated shapes) ,即绘制动画中的一帧。
◼ 第四步:恢复 canvas 状态,如果已经保存了 canvas 的状态,可以先恢复它,然后重绘下一帧。

二、canvas-绘制秒针-setinterval实现

2.1 settimout定时器的缺陷

settimeout定时器不是非常精准的,因为settimeout的回调函数是放到了宏任务中等待执行。
◼ 如果微任务中一直有未处理完成的任务,那么settimeout的回调函数就有可能不会在指定时间内触发回调
◼ 如果想要更加平稳和更加精准的定时执行某个任务的话,可以使用requestanimationframe函数。

在这里插入图片描述

<!doctype html>
<html lang="zh-ch">
<head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>document</title>

  <style>
    * {
      margin: 0;
      padding: 0;
    }
    body {
      padding: 100px;
      margin: auto;
      background-image: url(../images/grid.png);
    }
    canvas {
      background-color: rgba(255, 0, 0, 0.1);
    }
  </style>
</head>
<body>
  
  <!-- 如果不给宽高 默认宽300px 高150px -->
  <canvas id="box" width="300" height="300">
    您的浏览器不兼容canvas,请升级浏览器
  </canvas>

  <script>
    // 这个函数就是动画的一帧
    function draw(ctx, count) {
      // 清空画布
      ctx.clearrect(0, 0, 300, 300)
      ctx.save()
      // 绘图
      ctx.translate(100, 100)
      // math.pi * 2 圆
      // math.pi * 2 / 60 把圆分为60份
      ctx.rotate(math.pi * 2 / 60 * count)
      ctx.linewidth = 6
      ctx.linecap = 'round'
      ctx.strokestyle = 'green'
      ctx.beginpath()
      ctx.moveto(0, 0)
      ctx.lineto(0, -80)
      ctx.stroke()
      ctx.restore()
    }
    window.onload = function() {
      const canvasel = document.getelementbyid('box')
      if (!canvasel.getcontext) return
      let ctx = canvasel.getcontext('2d')
      let count = 0
      draw(ctx, count)

      setinterval(() => {
        count++
        if (count >= 60) {
          count = 0
        }
        draw(ctx, count)
      }, 1000);
    }
  </script>
</body>
</html>

三、canvas-绘制秒针–requestanimationframe实现

3.1 requestanimationframe函数

告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用该函数的回调函数来更新动画。
◼ 该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
◼ 若想在浏览器下次重绘之前继续更新下一帧动画,那么在回调函数自身内必须再次调用 requestanimationframe()
◼ 通常每秒钟回调函数执行 60 次左右,也有可能会被降低。

<!doctype html>
<html lang="zh-ch">
<head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>document</title>

  <style>
    * {
      margin: 0;
      padding: 0;
    }
    body {
      padding: 100px;
      margin: auto;
      background-image: url(../images/grid.png);
    }
    canvas {
      background-color: rgba(255, 0, 0, 0.1);
    }
  </style>
</head>
<body>
  
  <!-- 如果不给宽高 默认宽300px 高150px -->
  <canvas id="box" width="300" height="300">
    您的浏览器不兼容canvas,请升级浏览器
  </canvas>

  <script>
    // 这个函数就是动画的一帧
    function draw(ctx) {
      let second = new date().getseconds()
      ctx.clearrect(0, 0, 300, 300)
      ctx.save()
      ctx.translate(100, 100)
      ctx.rotate(math.pi * 2 / 60 * second)
      ctx.linewidth = 6
      ctx.linecap = 'round'
      ctx.strokestyle = 'green'
      ctx.beginpath()
      ctx.moveto(0, 0)
      ctx.lineto(0, -80)
      ctx.stroke()
      ctx.restore()
    
      requestanimationframe(() => {
        draw(ctx)
      })
    }

    window.onload = function() {
      const canvasel = document.getelementbyid('box')
      if (!canvasel.getcontext) return
      let ctx = canvasel.getcontext('2d')
      requestanimationframe(() => {
        draw(ctx)
      })
    }
  </script>
</body>
</html>

四、其他动画案例

案列地址

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com