2021SC@SDUSC山东大学软件学院软件工程应用与实践--quark renderer代码分析 第七篇 动画系统分析(6):requestAnimationFrame和track

2021SC@SDUSC

首先是requestanimationframe,兼容多种运行环境的 requestAnimationFrame 方法。  有两个重要的地方会依赖此方法:1.元素的渲染机制,在 Painter 类中会调用 2.元素的动画效果,在 Animation 类中会调用。这个是直接调用的,只要准备好更新屏幕上的动画,就应该调用此方法。这将要求在浏览器执行下一次重绘之前调用您的动画函数。回调方法传递一个参数 a DOMHighResTimeStamp​ ,它指示当前​时间(基于自时间origin以来的毫秒数)。当多个排队的回调requestAnimationFrame()开始在单个帧中触发时,每个回调都会收到相同的时间戳,即使在计算每个前一个回调的工作负载期间已经过了时间此时间戳是一个十进制数,以毫秒为单位,但最小精度为 1 毫秒(1000 微秒)。

在网上查找得知

requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点:

1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。

2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。

var _default = typeof window !== 'undefined' && (window.requestAnimationFrame && window.requestAnimationFrame.bind(window) || window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window) || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame) || function (func) {
  setTimeout(func, 16); // 1000ms/60,每秒60帧,每帧约16ms
};

在requestAnimationFrame中,有类似clearInterval这样的类似方法——cancelAnimationFrame(),cancelAnimationFrame()接收一个参数 requestAnimationFrame默认返回一个id,cancelAnimationFrame只需要传入这个id就可以停止了。默认情况下,requestAnimationFrame执行频率是1000/60,大概是16ms多执一次。

接着是track(轨道),其与元素(Element)上可以用来进行动画的属性一一对应。 元素上存在很多种属性,在动画过程中,可能会有多种属性同时发生变化, 每一种属性天然成为一条动画轨道,把这些轨道上的变化过程封装在 Track 类中。

function Track(options) {
    _classCallCheck(this, Track);

    this.element = options.element;
    this.path = options.path;
    this.delay = options.delay;
    this.currentValue = null;
    this.isFinished = false;
    this.keyframes = [];
    this.timeline;
  }

首先是自然是定义各个属性值的行为,属性的种类与元素上的属性一一对应。

_createClass(Track, [{
    key: "addKeyFrame",
    value: function addKeyFrame(kf) {
      this.keyframes.push(kf);
    }

然后就是向轨道中添加关键帧。其中kf数据结构为 {time:0,value:0}。

{
    key: "nextFrame",
    value: function nextFrame(time, delta) {
      if (!this.timeline) {
        return;
      }

      var result = this.timeline.nextFrame(time, delta);

      if (dataUtil.isString(result) && result === 'destroy') {
        this.isFinished = true;
      } // console.log(`result=${result}`);


      return result;
    }

这里是进入下一帧,time是当前时间而delta是时间偏移量,调用了timeliness中的对应部分。

{
  key: "fire",
  value: function fire(eventType, arg) {
    this.timeline.fire(eventType, arg);
  }

当获得关键词为“fire”时,就会执行触发事件的操作。

key: "start",
    value: function start() {
      var loop = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
      var easing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
      var forceAnimate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

      var options = this._parseKeyFrames(easing, this.path, loop, forceAnimate); 
      if (!options) {
        return null;
      }

      var timeline = new Timeline(options);
      this.timeline = timeline;
    }

当关键词为“start”时,轨道会执行动画开始操作,这时会判定动画是否循环,是够调用缓动引擎以及在特定情况下是否需要强制开启动画,当然,在this._parseKeyFrames中如果传入的参数不正确,则无法构造实例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云亦纵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值