简体   繁体   English

如何使用requestAnimationFrame实现平滑滚动?

[英]How to implement a smooth scroll using requestAnimationFrame?

I want to make a good smooth scroll effect in my webpage, and I see that one of the best way is using the requestAnimationFrame. 我想在网页中实现良好的平滑滚动效果,并且我看到最好的方法之一是使用requestAnimationFrame。

I found this polyfill by Jed Schmidt: https://gist.github.com/997619 我通过Jed Schmidt找到了这个polyfill: https : //gist.github.com/997619

And this one by Paul Irish: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ 保罗·爱尔兰(Paul Irish)的这篇文章: http//www.paulirish.com/2011/requestanimationframe-for-smart-animating/

But to be honest, I don't know how to use it to create the smooth effect. 但是老实说,我不知道如何使用它来产生平滑效果。 In the past I checked some plugins: nicescroll (I don't like it because it changes the scrollbar style), smoothscroll.js (this one only works on Chrome), and some others that only work on mousewheel, but not when you click the Re Pag, Av Pag, the spacebar, etc. 过去,我检查了一些插件:nicescroll(我不喜欢它,因为它更改了滚动条样式),smoothscroll.js(该插件仅在Chrome上有效)以及其他一些插件仅在鼠标滚轮上有效,但在单击时不起作用Re Pag,Av Pag,空格键等。

I can provide an example on this page: http://cirkateater.no/ The scroll effect is really nice and works efficiently. 我可以在此页面上提供一个示例: http : //cirkateater.no/滚动效果非常好并且有效。 It's also cross browser! 它也是跨浏览器! But taking a look in its JS code, I only see a huge function for parallax, and I'm not sure if what I want is into this function. 但是看看它的JS代码,我只会看到一个巨大的视差函数,而且我不确定我想要的东西是否包含在该函数中。

Could you tell me where I start? 你能告诉我我从哪里开始吗? I will update the progress here. 我将在这里更新进度。

PD: Actually, I've spent a day trying to implement it through non-sense actions about copy-paste into my scripts.js file. PD:实际上,我花了整整一天的时间尝试通过无意义的操作将其复制粘贴到scripts.js文件中来实现它。 I'm not an expert on JS, but I deduce it's something difficult to do. 我不是JS方面的专家,但我推断这很难做。

Edit 1: I already have something. 编辑1:我已经有东西。 First, the polyfill: 首先,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);
    };
}());

And the smooth mouse wheel: 平滑的鼠标滚轮:

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);
}

We can begin from here. 我们可以从这里开始。 Now I only need to make a better improvement to have this smooth effect when I press the arrow keys, Re Page, Av Page, etc. 现在,当我按箭头键,“翻页”,“平均页”等时,只需做出更好的改进即可获得这种平滑效果。

I have the way to do that as I expected: 如我所料,我有办法做到这一点:

// 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();
});

And this is the HTML structure: 这是HTML结构:

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

It works but it's not perfect. 它有效,但并不完美。 For example, having the WP admin bar enabled for a user, it will position the content under the admin-bar, and it will leave a blank space after the footer. 例如,为用户启用WP管理栏,它将内容放置在管理栏下,并在页脚后留下空白。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM