【问题标题】:How to implement a smooth scroll using requestAnimationFrame?如何使用 requestAnimationFrame 实现平滑滚动?
【发布时间】:2015-03-04 16:13:16
【问题描述】:

我想在我的网页中制作一个良好的平滑滚动效果,我发现最好的方法之一是使用 requestAnimationFrame。

我发现了 Jed Schmidt 的这个 polyfill:https://gist.github.com/997619

还有这个来自 Paul Irish:http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

但老实说,我不知道如何使用它来创建平滑效果。过去我检查了一些插件:nicescroll(我不喜欢它,因为它改变了滚动条样式),smoothscroll.js(这个只适用于 Chrome),还有一些只适用于鼠标滚轮的插件,但当你点击时不适用Re Pag、Av Pag、空格键等

我可以在此页面上提供一个示例:http://cirkateater.no/ 滚动效果非常好,并且有效。它也是跨浏览器!但是看它的JS代码,我只看到一个巨大的视差函数,我不确定我想要的是不是这个函数。

你能告诉我从哪里开始吗?我会在这里更新进度。

PD:实际上,我花了一天时间尝试通过将复制粘贴到我的 scripts.js 文件中的无意义操作来实现它。我不是 JS 方面的专家,但我推断这很难做到。

编辑 1: 我已经有了一些东西。一、polyfill:

(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
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);
    };
}());

还有平滑的鼠标滚轮:

var html = document.documentElement;
var rAF, target = 0, scroll = 0;

onmousewheel = function (e) {
e.preventDefault();
var scrollEnd = html.scrollHeight - html.clientHeight;
target += (e.wheelDelta > 0) ? -70 : 70;
if (target < 0)
    target = 0;
if (target > scrollEnd)
    target = scrollEnd;
if (!rAF)
    rAF = requestAnimationFrame(animate);
};

onscroll = function () {
if (rAF)
    return;
target = pageYOffset || html.scrollTop;
scroll = target;
};

function animate() {
scroll += (target - scroll) * 0.1;
if (Math.abs(scroll.toFixed(5) - target) <= 0.47131) {
    cancelAnimationFrame(rAF);
    rAF = false;
}
scrollTo(0, scroll);
if (rAF)
    rAF = requestAnimationFrame(animate);
}

我们可以从这里开始。现在我只需要在按方向键、Re Page、Av Page等时做出更好的改进就可以有这种流畅的效果了。

【问题讨论】:

    标签: javascript requestanimationframe


    【解决方案1】:

    按照我的预期,我有办法做到这一点:

    // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
    // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
    
    // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
    
    // MIT license
    (function () {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    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);
        };
    }());
    
    
    ('ontouchend' in document) || jQuery(function($){
    
    var scrollTop = 2, tweened = 0, winHeight = 0, ct = [], cb = [], ch = [], ph = [];
    var wrap = $('#wrap').css({position:'fixed', width:'100%', top:0, left:0})[0];
    var fake = $('<div>').css({height: wrap.clientHeight}).appendTo('body')[0];
    
    var update = function(){
            window.requestAnimationFrame(update);
            if(Math.abs(scrollTop-tweened) > 1){
                var top = Math.floor(tweened += .25 * (scrollTop-tweened)),
                    bot = top + winHeight, wt = wrap.style.top = (top*-1) + 'px';
    
                for(var i = plax.length; i--;)if(cb[i] > top && ct[i] < bot){
                    plax[i].style.top = ((ct[i] - top) / Math.max(ph[i] - ch[i], winHeight - ch[i]) * (ch[i] - ph[i])) + 'px';
                }
            }
        };
    
    var listen = function(el,on,fn){(el.addEventListener||(on='on'+on)&&el.attachEvent)(on,fn,false);};
    var scroll = function(){scrollTop = Math.max(0, document.documentElement.scrollTop || window.pageYOffset || 0);};
    
    listen(window, 'scroll', scroll);
    update();
    });
    

    这是 HTML 结构:

    <html>
        <body>
            <div id="wrap">
                <!-- The content goes here -->
            </div>
        </body>
    </html>
    

    它有效,但并不完美。例如,为用户启用了 WP 管理栏,它会将内容定位在管理栏下方,并且在页脚之后会留下一个空白区域。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-14
      • 1970-01-01
      • 1970-01-01
      • 2016-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多