zoukankan      html  css  js  c++  java
  • requestAnimationFrame之缓动的应用

    之前需要使用的定时器的时,立马想到的是setInterval(),用着用着就成为习惯,并没有遇到什么不妥之处。习惯性的操作往往容易让一个人拒绝尝试一些其他的方法。现在的方法用得好好的,没事干啥找其他法子。

    摈弃习惯性操作的思想,没事还真得去尝试一些新方法,不然整天敲一样的代码不无聊么?

    对于requestAnimationFrame这个东东,其实很早就知道了,但是也就只是局限于‘知道’而已。

    直到后面的项目中,在写一个关于榜单滚动的模块,开始当然用的还是setInterval(),榜单列表每秒向上移动1px,很快项目写完了,回头乍看,榜单在滚动的时候,隐隐约约看到跳帧现象,而且页面背景和榜单背景夜色是反色,看起来效果还是不尽如人意。

    这时候我开始寻求优化这个问题,捣鼓好久,打算从从滚动动画开刀,查阅资料,动画优化。。。。。。顺藤摸瓜,就找到了requestAnimationFrame。之前也听说过这个,但是就是没有认真捣鼓过,作为一名有态度的前端人员,明明知道这个样子,你竟然不去捣鼓它为什么是这样子,这俨然和你的气质不符合的。

    requestAnimationFrame,从我英语专八的角度翻译过来就是:请求动画帧。这也真是太见名知意了。

    那么问题来了,为什么会出现这个东西呢?这个东西有什么优越的地方呢?它怎么用呢?

    本着‘存在即有道理’的态度。我倒是来会会这厮~~~

    每秒60帧,显示频率16.7ms这是现如今大部分浏览器的标配,当显示频率低于16.7ms的时候,就会发现之前所说的跳帧。当你主动使用setInterval()或者setTimeout()时候,如果显示频率为10m或者5ms,这时候就会出现这种情况,这肯定是会降低其他应用的性能的,这也是我们不能容忍的。

    为什么会这样子呢?这就关于到资源的问题。浏览器高效的利用资源的方式应该是:让我通知大家开始和结束,我让你的绘制频率是多少就多少,跟着我走就好了,别瞎比比。

    requestAnimationFrame这个API正是扮演这种被使唤的角色而应运而生了。浏览器大哥你放心,我来优化动画。如果我的优点该不够明显,让度娘说说吧:

    浏览器可以优化并行的动画动作,更合理的重新排列动作序列,并把能够合并的动作放在一个渲染周期内完成,从而呈现出更流畅的动画效果。比如,通过requestAnimationFrame(),JS动画能够和CSS动画/变换或SVG SMIL动画同步发生。另外,如果在一个浏览器标签页里运行一个动画,当这个标签页不可见时,浏览器会暂停它,这会减少CPU,内存的压力,节省电池电量。

    怎么用?很简单。懒得打了。。。。

    // 当前时间
    var start = 0;
    var begin = 0;//开始位置
    var end = 100;//结束位置
    var during = 100;// 持续时间
    var step = function() {
        // 当前的运动位置
        var left = Math.tween.Linear(start, begin, end, during);
        // 位移
        eleBall.style.transform = 'translateX(' + left + 'px)';
        
        // 时间递增
        start++;
        // 如果还没有运动到位,继续
        if (start <= during) {
             requestAnimationFrame(step);
        } else {
            // 动画结束,这里可以插入回调...
            // callback()...
        }
    };
    // 开始执行动画
    step();

    对应的清除方法:cancelAnimationFrame()

    新东西兼容性总是不是十全十美,不过没关系,好东西总会有各种大神去使之完美。

    Opera浏览器的技术师Erik Möller 把这个API的兼容性进行封装

    (function() {
        var lastTime = 0;
        var vendors = ['webkit', 'moz'];
        for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
            window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
            window.cancelAnimationFrame =
              window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
        }
    
        if (!window.requestAnimationFrame)
            window.requestAnimationFrame = function(callback, element) {
                var currTime = new Date().getTime();
                var timeToCall = Math.max(0, 16 - (currTime - lastTime));
                var id = window.setTimeout(function() { callback(currTime + timeToCall); },
                  timeToCall);
                lastTime = currTime + timeToCall;
                return id;
            };
    
        if (!window.cancelAnimationFrame)
            window.cancelAnimationFrame = function(id) {
                clearTimeout(id);
            };
    }());

    OK,这不是就好了吗。

    缓动的应用

    上面的例子已经用了

    Math.tween.Linear(start, begin, end, during);
    再来一个直观的例子~~~
    // 滚动到顶部缓动实现
    var backToTop = function (rate) {
        var doc = document.body.scrollTop? document.body : document.documentElement;
        var scrollTop = doc.scrollTop;
        
        var top = function () {
            scrollTop = scrollTop + (0 - scrollTop) /2;
            if (scrollTop < 1) {
                doc.scrollTop = 0;
                return;
            }
            doc.scrollTop = scrollTop;
            requestAnimationFrame(top);    
        };
        top();
    };





  • 相关阅读:
    BZOJ 3160 万径人踪灭
    BZOJ 2160 拉拉队排练
    模板 manacher算法
    [Tjoi2016&Heoi2016]求和
    [HZOI 2015]疯狂的机器人
    [BZOJ3456]城市规划
    BZOJ 4372 烁烁的游戏
    洛谷3794 签到题IV
    BZOJ 3730 震波
    BZOJ 4916 神犇和蒟蒻
  • 原文地址:https://www.cnblogs.com/leaf930814/p/6323445.html
Copyright © 2011-2022 走看看