带有动画效果的滚动至指定位置

17

我该如何为这个函数添加缓动/动画/缓慢移动效果?目前它只是跳转。现在它应该通过动画移动到“锚点”。

<script type='text/javascript'>
        setTimeout("window.scrollBy(0,270);",3000);
</script>

5
不要将字符串传递给setInterval()setTimeout()函数。这样做就像使用eval()一样糟糕,会导致代码难以阅读并且可能不安全,因为需要将变量插入到字符串中而不是直接传递变量。正确的解决方法是使用setInterval(function() { /* your code *) }, msecs);。对于setTimeout()也是同样的情况。如果你只想调用一个没有参数的函数,也可以直接传递函数名称:setInterval(someFunction, msecs);(注意函数名称后面没有括号)。 - ThiefMaster
考虑使用一些现有的库。 - ThiefMaster
这个听起来不错,但是我该如何添加页面滚动多少秒后的时间呢?http://flesler.blogspot.se/2007/10/jqueryscrollto.html - Max
9个回答

45

还可以通过使用request animation frame来使用纯JavaScript实现。

// first add raf shim
// http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();

// main function
function scrollToY(scrollTargetY, speed, easing) {
    // scrollTargetY: the target scrollY property of the window
    // speed: time in pixels per second
    // easing: easing equation to use

    var scrollY = window.scrollY,
        scrollTargetY = scrollTargetY || 0,
        speed = speed || 2000,
        easing = easing || 'easeOutSine',
        currentTime = 0;

    // min time .1, max time .8 seconds
    var time = Math.max(.1, Math.min(Math.abs(scrollY - scrollTargetY) / speed, .8));

    // easing equations from https://github.com/danro/easing-js/blob/master/easing.js
    var PI_D2 = Math.PI / 2,
        easingEquations = {
            easeOutSine: function (pos) {
                return Math.sin(pos * (Math.PI / 2));
            },
            easeInOutSine: function (pos) {
                return (-0.5 * (Math.cos(Math.PI * pos) - 1));
            },
            easeInOutQuint: function (pos) {
                if ((pos /= 0.5) < 1) {
                    return 0.5 * Math.pow(pos, 5);
                }
                return 0.5 * (Math.pow((pos - 2), 5) + 2);
            }
        };

    // add animation loop
    function tick() {
        currentTime += 1 / 60;

        var p = currentTime / time;
        var t = easingEquations[easing](p);

        if (p < 1) {
            requestAnimFrame(tick);

            window.scrollTo(0, scrollY + ((scrollTargetY - scrollY) * t));
        } else {
            console.log('scroll done');
            window.scrollTo(0, scrollTargetY);
        }
    }

    // call it once to get started
    tick();
}

// scroll it!
scrollToY(0, 1500, 'easeInOutQuint');

这是一个很棒的答案,帮助我可视化使用JavaScript扩展其自身核心功能的高级技术。谢谢! - lakewood
为了支持IE11,您可以使用window.pageYOffset代替window.scrollY - Beat Sprenger
这个能和元素的.scrollTop属性一起使用吗?我用不了。 - Julius
我希望我能够点赞10次,这正是我在寻找的!如果您将targetY计算为targetY = window.scrollY + offset,则此功能也可以用于scrollBy(dY) - mlz7

23

请注意,它在IE/Edge中不起作用:https://caniuse.com/#feat=mdn-api_scrolltooptions_behavior - burtek

13

此答案修改而来:

function scrollBy(distance, duration) {

    var initialY = document.body.scrollTop;
    var y = initialY + distance;
    var baseY = (initialY + y) * 0.5;
    var difference = initialY - baseY;
    var startTime = performance.now();

    function step() {
        var normalizedTime = (performance.now() - startTime) / duration;
        if (normalizedTime > 1) normalizedTime = 1;

        window.scrollTo(0, baseY + difference * Math.cos(normalizedTime * Math.PI));
        if (normalizedTime < 1) window.requestAnimationFrame(step);
    }
    window.requestAnimationFrame(step);
}

这将使您能够平稳地滚动指定的距离。


4

这个可以实现,假设你需要平滑地滚动到页面顶部。

const scrollToTop = () => {
  const c = document.documentElement.scrollTop || document.body.scrollTop;
  if (c > 0) {
    window.requestAnimationFrame(scrollToTop);
    window.scrollTo(0, c - c / 8);
  }
};

1
这个会结束吗?基本上,你正在执行 c = c * 7/8,它永远不会真正接近 0,对吧?它将会收敛到 0,并且由于 JS 的精度限制,它最终可能会被四舍五入为 0,但仍然如此。 - cutsoy

2

我自己解决了。由于 WordPress 和 jQuery.noConflict 模式的影响,我不得不修改代码:

<script type="text/javascript">
        (function($){
        $(document).ready(function(){
            setTimeout(function() {
            $('body').scrollTo( '300px', 2500 );
        }, 3000);
        });
        }(jQuery));
</script>

谢谢大家!!!


2

1

0

使用jQuery可以使这个过程变得更加容易,也许可以使用scrollto插件。http://flesler.blogspot.se/2007/10/jqueryscrollto.html

考虑这样一个解决方案:

<script type='text/javascript' src='js/jquery.1.7.2.min.js'></script>
<script type='text/javascript' src='js/jquery.scrollTo-min.js'></script>
<script type='text/javascript' src='js/jquery.easing.1.3.js'></script><!-- only for other easings than swing or linear -->
<script type='text/javascript'>
$(document).ready(function(){
    setTimeout(function() {
    $('html,body').scrollTo( {top:'30%', left:'0px'}, 800, {easing:'easeInBounce'} );
}, 3000);
});
</script>

当然你需要下载这些脚本。
请参考http://jsfiddle.net/7bFAF/2/上的一个可工作示例。

我该如何添加时间,以便在多少秒后页面滚动? - Max
我尝试了这个代码,但它没有起作用。code <script type='text/javascript'> $(document).ready(function(){ $('window').delay(3000).scrollTo( 30%,0, 800, {easing:'elasout'} ); }); </script> code - Max
@max,“elasout”缓动效果仅在演示页面上定义。除了默认的swing或linear版本之外,您需要缓动插件,就像我上面的示例一样。还要注意,我编辑了函数以使用timeout()而不是delay(),因为delay()仅适用于本机jQuery效果。使用timeout()更通用。 - jtheman
这个函数本身没有任何问题。然而,文件“http://domain.de/wp-content/themes/intellicig/library/libs/js/jquery.scrollTo-1.4.3-min.js”似乎不存在...为了测试目的,尝试完全删除缓动部分(我怀疑您不需要easeInBounce?)... - jtheman
1
他在 document ready 函数方面遇到了问题。http://cl.ly/image/0X02160j2x0g http://cl.ly/image/0a0m1f3c0a3a - Max
显示剩余2条评论

0

我们可以使用CSS属性scroll-behavior来简化它。

html {
  scroll-behavior: smooth;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接