如何在jQuery中实现“平滑滚动”鼠标滚轮规则?

25

你好!我的问题是:

我如何控制或指定文档如何滚动以到达所需位置,无论是通过鼠标滚轮还是拖动滚动条描述的。我想要的是克服页面默认的滚动方法。
目前的情况是,每次在滚动轮上进行单击时,页面会直接跳转到下方x像素的位置,或者直接跳转到您拖动滚动条的位置。 我正在寻找一种简单的扩展方式,可以应用特定的滚动规则。原则很简单。强制加速,这将防止页面过快移动而不会先加速。以px/sec为速率设置-并提供应用缓动函数的选项...页面最大px/sec可以滑动/移动/拖动。第三个是减速规则,在页面接近其目标位置(以%、px为单位)时应用。这可能必须通过多种方式计算,并且可能更加棘手。例如,在滚动最后25像素到达目标位置时,应用减速。还有更多...我想要准备的主要问题是确保完全支持小页面滚动而不会出现故障。
有哪些jQuery方法可以用来控制文档呢? _kyle

更新: 感谢您关注这个问题。好消息。找到了一个很棒的插件,希望可以处理成支持所需效果,嘿!我实现了一个整个页面容器,并使用了这个巧妙的jScrollPane脚本来控制页面的滚动 http://jscrollpane.kelvinluck.com/fullpage_scroll.html

页面的性能已经有了很大的改善。每次从滚轮上单击时,滚动小步长仅相当于浏览器本机滚动小步长的三分之一到一半,因此移动速度较慢,这很好,肯定是可以调整的。
不过我们仍然有页面运动卡顿的问题。

我本人编写JavaScript,但更多的是重新编写。

我认为需要完成的是构建一个像素“队列”,以便在页面上滚动,总时间累加: 然后定义和执行一个动画轨迹分为三个阶段,一个缓入加速,最大滚动速度阶段和减速阶段。

请问有什么建议可以

  1. 将鼠标滚轮从其原生功能中分离出来,使其不再滚动页面。

  2. 监听鼠标滚动的滑轮位置;并在出现滚轮位置变化时:初始化核心功能以开始移动页面,并将额外的滚动位置变化添加到“队列”中,重新计算并应用于窗口滚动替换先前的totaldistancetoscroll,然后计算下一个totaldistancetoscroll,这提供了一种方式来预测目的地并减速。核心功能不希望被重启,因为在加速时可能会发生多次滚轮位置变化,但只需应用重新计算何时何地减速即可。

很抱歉没有发布任何实际代码,不确定从哪里开始,希望有人知道mwintent是否适用于这个问题,如果是这样的话:也许还有一些想法如何应用减速到滚动中,这似乎是期望效果和类似的当前插件状态之间的唯一两种区别。


这听起来对用户来说可能相当恼人。 - Peter Olson
你是否在考虑类似于iPhone的滚动效果? - Matt Ball
非常喜欢类似iPhone的滚动效果,感谢提供链接。除了支持平稳的鼠标滚轮滚动外,不支持页面拖动...也不需要“overthrow”效果...页面将停在所需位置,而不会继续“漂浮”。=) - bnbgnoise
可能是重复问题:https://dev59.com/T2ox5IYBdhLWcg3wi0zF?lq=1 - Anderson Green
7个回答

14

我想做的是在不支持平滑滚动、默认关闭或实现不好的浏览器上模拟浏览器的平滑滚动效果。

感谢lumbric的答案,我想出了以下解决方案:

$(function () {

    var top = 0,
        step = 55,
        viewport = $(window).height(),
        body = $.browser.webkit ? $('body') : $('html'),
        wheel = false;


    $('body').mousewheel(function(event, delta) {

        wheel = true;

        if (delta < 0) {

            top = (top+viewport) >= $(document).height() ? top : top+=step;

            body.stop().animate({scrollTop: top}, 400, function () {
                wheel = false;
            });
        } else {

            top = top <= 0 ? 0 : top-=step;

            body.stop().animate({scrollTop: top}, 400, function () {
                wheel = false;
            });
        }

        return false;
    });

    $(window).on('resize', function (e) {
        viewport = $(this).height();
    });

    $(window).on('scroll', function (e) {
        if (!wheel)
            top = $(this).scrollTop();
    });

});

在您的页面上放置足够长以具有滚动条的内容。然后使用鼠标滚轮,在所有浏览器中都可以使用。我使用了jQuery-1.7.2和lumbric帖子中提到的mousescroll插件。

step变量表示每次鼠标滚轮事件要滚动多少像素。我发现在大多数系统上默认值为约55像素。

此外,您可能想要改变动画的速度,除此之外,其余的代码逻辑都需要使事物正常工作。

编辑:请注意,我已经将上述功能提取到一个方便使用的jQuery插件中。


这种解决方案的问题在于,如果页面上有一些具有自己滚动条的元素,则它们将被忽略。 - Adam Pietrasiak

4

我有一个非常类似的问题。我想要更改普通页面的滚动功能。我希望每次滚动都恰好是特定高度,这样页面只会停在非常特定的位置。

我通过以下方式实现了它:

1. 使用插件

下载并包含以下两个jQuery插件和jQuery本身:

2. 鼠标滚轮事件

最简单的方法是使用鼠标滚轮插件,如下所示:

$('body').mousewheel(function(event, delta) { /* code here */ });

变量delta的值会根据鼠标滚轮向上或向下滚动而变为负数或正数。如果返回false,它会禁用正常的滚动。(我认为是这样)。
3. 滚动方法
为了滚动页面,我使用了scrollTo方法,但是任何其他插件(例如在其他答案中建议的Smooth Scroll)也可以实现。
4. 完整代码
将此代码放置在HTML文件的头部。
<script type="text/javascript" src="jquery-1.6.4.min.js"></script>
<script type="text/javascript" src="jquery.scrollTo-1.4.2-min.js"></script>
<script type="text/javascript" src="jquery.mousewheel.min.js"></script>
<script type="text/javascript">
    $(document).ready(function() {          
        $('body').mousewheel(function(event, delta) {
            # This if might not be very elegant!
            if (delta < 0) {
                $('body').scrollTo('+=100', 1500 );
            }
            else
                $('body').scrollTo('-=100', 1500 );

            return false;
        });
    });
</script>

5. 演示

我在这里创建了一个演示:http://pastehtml.com/view/ba0ziusqk.html


这是一个不错的开始,但我似乎无法弄清楚如何使其更加流畅(例如,如果您多次向下滚动,它会滚动一点,然后慢慢停止,然后再滚动一点,然后再慢慢停止等等...) - Nathan J.B.
这正是我想做的(它不是一个普通的页面)。如果你想要平滑的滚动感觉,你必须改变scrollTo的缓动效果。阅读这个来了解更多信息。你可能需要线性缓动,所以这将是命令:jQuery('body').scrollTo('-=404', 1500, {easing : 'linear'} )但是警告:如果你这样做,那些想快速滚动你的页面的人可能会非常恼火并离开! - lumbric
嗯...我刚刚注意到我的最后一条评论可能并不那么有用。如果你真的想让滚动更加平滑,为什么不使用Alex提到的插件呢? - lumbric

2

这里有一个好的解决方案,看看这个网址:http://ataredo.com/morphology/lucidscroll/

<script src="file-directory/jquery.js"></script>
<script src="file-directory/lucid.js"></script>

<script>
$(window).on('load', function() {

  $(this).impulse();
});
</script>

2
你想试试这个:https://github.com/galambalazs/smoothscroll-for-websites。它有很好的设置可以调整动画效果,而且看起来维护得很好。
// Scroll Variables (tweakable)
var defaultOptions = {

    // Scrolling Core
    frameRate        : 100, // [Hz]
    animationTime    : 1200, // [ms]
    stepSize         : 80, // [px]

    // Pulse (less tweakable)
    // ratio of "tail" to "acceleration"
    pulseAlgorithm   : true,
    pulseScale       : 4,
    pulseNormalize   : 1,

    // Acceleration
    accelerationDelta : 50,  // 50
    accelerationMax   : 3,   // 3

    // Keyboard Settings
    keyboardSupport   : true,  // option
    arrowScroll       : 50,    // [px]

    // Other
    touchpadSupport   : false, // ignore touchpad by default
    fixedBackground   : true, 
    excluded          : ''    
};

这是我迄今找到的最好的脚本。它运行平稳,却不会劫持默认滚动。它实际上看起来与默认滚动完全一样,但在最后它能够使其更平稳。是最好的建议!请访问https://codepen.io/AartdenBraber/pen/YVXVoB 进行测试。 - Aart den Braber

1

我的移动效果解决方案

    <div id="parent">
    <div id="child">aaa aaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaa abbbbbbbbbbbbbbbbb bbbbbbbbbbbbcc ccccccc ccccccccccc cccccccd ddddddd ddd ddddd ddddd dddddddd aaaaaaaaaaaa aaaaaaaa aaa</div>

        #parent {
        width: 300px;
        height: 300px;
        background-color: #aaa;
        margin: auto auto;
        overflow: hidden;
    }
    #child {
        width: 200px;
        height: 800px;
        background-color: #999;
        margin: auto auto;
        text-align: justify;
        position: relative;
        top: 0;
        -webkit-transition: all 0.5s ease-out;
}




$('#parent').bind('mousewheel', function (e) {
        if (!(e.originalEvent.wheelDelta == 120)) {
            var top = parseInt($("#child").css("top"));
            $("#child").css("top", (top - 100) + "px");
            top = parseInt($("#child").css("top"));
            if (top <= -500) {
                setTimeout(function () {
                    $("#child").css("top", "-500px");
                }, 100);
            }
        } else {
            var top = parseInt($("#child").css("top"));

            $("#child").css("top", (top + 100) + "px");
            top = parseInt($("#child").css("top"));
            if (top >= 0) {
                setTimeout(function () {
                    $("#child").css("top", "0");
                }, 100);
            }
        }
    });

{{链接1:THE DEMO}}


1
Karl Swedberg开发了一个名为Smooth Scroll的jQuery插件,听起来可能正是你需要的。

啊...谢谢,我实际上在寻找与平滑滚动和jquery相关的任何插件,但没有发现像这样的东西,这对我来说是一个开始。我想弄清楚如何使它适用于当鼠标滚轮移动页面或直接拖动页面时,我将不得不查看那个鼠标滚轮意图脚本。再次感谢 =) - bnbgnoise

0
var $window              = $(window),
    scrollDistance   = 300,
    scrollSpeed      = 500,
    scrollEffect     = 'swing',
    scrollAmount     = 1,
    smoothScroll;

if (! ('ontouchstart' in document.documentElement) && ! $('body').hasClass('modal-open')) {

        $window.on("mousewheel DOMMouseScroll", function (event) {

            event.preventDefault();

            if (smoothScroll) {

                // Start scrolling while waiting for final scoll amount (user stopped wheeling)
                if (scrollAmount == 1) {
                    var delta = event.originalEvent.wheelDelta / 120 || -event.originalEvent.detail / 3;
                    var finalScroll = $window.scrollTop() - parseInt(delta * (scrollDistance * scrollAmount));

                    $('html, body').stop().animate({ scrollTop: finalScroll }, scrollSpeed, scrollEffect);
                }

                // Increase scroll amount
                scrollAmount++;

                // Clear current timeout
                clearTimeout(smoothScroll);
            }

            // Set animated scroll
            smoothScroll = setTimeout(function() {

                var delta = event.originalEvent.wheelDelta / 120 || -event.originalEvent.detail / 3;
                var scrollTop = $window.scrollTop();
                var finalScroll = scrollTop - parseInt(delta * (scrollDistance * scrollAmount));

                // Reset scroll amoount
                scrollAmount = 1;

                $('html, body').stop().animate({ scrollTop: finalScroll },
                    (scrollSpeed*scrollAmount),
                    scrollEffect
                );

                // Clear timeout holder
                smoothScroll = null;

            }, 100);

        });
}

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