• requestAnimationFrame 的实验性实践


    记得当 requestAnimationFrame 出现时我立马就石更了,就跟初次玩耍 transition 时一样,欣喜若狂...

    然后,然后特么的就懵逼了,这明明就是口挖不通的深井呀(如果是我傻,那我认了...)

    一. 简介

    随着页面上动画的使用越来越频繁,为了避免过多的定时器带来额外系统开销,一般的动画组件都会采用“统一帧管理”:只使用一个定时器,在每一动画帧依次调用所有注册的动画事件。

    后来,一些浏览器推出各自私有Api提供动画管理,W3C也出了一份 WindowAnimationTiming interface 规范,也就是 requestAnimationFrame。

    动画四要素: 时长(dur),即动画播放的时间总长。 进度(per),播放的进度,在区间 [0,1] 之内。 帧间隔时间(frameTime),即多长时间播放一帧。 动画函数(animFun),它是每一帧的渲染函数。

    对动画优化而言,最需考虑的就是帧间隔时间 frameTime。

    原生实现里的 frameTime 被设计为可根据 CPU 使用率、window 是否被最小化、元素是否被隐藏等因素进行动态调整。

    浏览器可根据实际情况降低 fps 甚至停止动画。这比以前的 setTimeout 和 setInterval 不知道好到哪里去了。

    二. 实践

    简单点来讲:

    注册动画使用 requestAnimactionFrame 函数,接受动画函数callback作为参数,并返回动画ID;

    移除动画使用 cancelRequestAnimationFrame 函数,参数是动画ID;

    动画函数执行时,会传入当前系统时间戳。

    function timeout(dur, animFun, callback) {
        var nowTime, Timer, duration;
        function _run() {
            var per = Math.min(1.0, (Date.now() - nowTime) / duration);
            if (per >= 1) {
                _stop();
                if (callback) callback.call(this, duration);
            } else {
                if (animFun) animFun.call(this, per, duration);
                Timer = window.requestAnimationFrame(_run);
            }
        }
        function _start() {
            _go(dur); return this;
        }
        function _go(dur) {
            duration = dur, nowTime = Date.now(), _run(); return this;
        }
        function _stop() {
            window.cancelAnimationFrame(Timer); return this;
        }
        return {
            start: _start, stop: _stop, go: _go,
        };
    }
    
    var start = Date.now();
    timeout(1000, function(per, dur){
        var offset = 500 * per + 0;
        if (per < 1) console.log('方块将从 0 移动' + offset + 'px 到 500');
    }, function() {
        console.log(Date.now() - start);
    }).start();

    三. 遗留的问题

    在进行每一秒运行一次的倒计时会误差很严重,并不是标准的一秒。

    这源于 requestAnimactionFrame 的智能,会根据现有性能进行的速率调整....虽然很好,但好尴尬呀...

    上文说到,“动画函数执行时,会传入当前系统时间戳”,这句话并不可信,

    因为 webkitRequestAnimationFrame 是可以的,但 requestAnimactionFrame 不对。

    其次, firefox 里有 mozRequestAnimationFrame,却没有对应的 mozCancelRequestAnimationFrame,非常坑爹...

    所以得这样 window.removeEventListener('MozBeforePaint', animFun, false);

    开始还跟同事说它很牛逼牛逼呀,现在啪啪打脸,还得保持微笑,因为它是如此的令人期待...

  • 相关阅读:
    《Linux内核设计与实现》读书笔记(4) 中断和中断处理程序
    《Linux内核设计与实现》读书笔记(11) 内存管理(1)
    《Linux内核设计与实现》读书笔记(10) 定时器和时间管理(2)
    《Linux内核设计与实现》读书笔记(7) 内核同步方法(1)
    《Linux内核设计与实现》读书笔记(9) 定时器和时间管理(1)
    Mac os 10.7.1(Lion) 下vmware fusion里的windows有时无法工作在NAT模式下的问题
    偶然发现7年前受到的offer。7年,一晃而过
    IE下对文件(图片)进行base64转换
    IE这个bug真是弱爆了
    腾讯举办创意马拉松活动庆祝成立14周年
  • 原文地址:https://www.cnblogs.com/foreverZ/p/6016846.html
Copyright © 2020-2023  润新知