JavaScript - 使用鼠标滚轮实现流畅的视差滚动

17

我有一个页面,我正在应用视差效果。这是通过使用translate3d实现的。现在,虽然这很有效,但我想知道如何在使用鼠标滚轮滚动时覆盖默认的“步骤”?

如果我使用滚动条滚动,一切都很好。但是用鼠标滚轮就会很卡顿。

我正在以一种非常直接的方式进行:

    var prefix = Modernizr.prefixed('transform');
    $window.on('scroll', function(){
        var scroll_top = $window.scrollTop();
        if(scroll_top < forside_infographics_offset){
            $_('#slider').css(prefix , "translate3d(0,"+(scroll_top/3)+"px,0)");
        }

    });

我最近发现一个网站,它的滚动非常流畅,而且还有一个带有步进的鼠标滚轮。我试图查看代码,似乎他在使用requestAnimationFrame,但是他是如何实现这种精确的滚动效果的,我不确定。

http://cirkateater.no/

你有什么想法吗?

6个回答

19

经过大量研究,我发现了一种相当简单的解决方案 :) http://bassta.bg/demos/smooth-page-scroll/

有趣的是,我根本不需要修改现有代码。这个方法覆盖了默认的滚动行为,同时保留了事件打开,可以像平常一样使用。

编辑:这真的是一个很糟糕的主意。永远不要劫持和覆盖预期的行为。我猜当时我对动画过于着迷了,做得太过火了。值得庆幸的是,我们都在学习和扩展对良好用户体验原则的认识 :)


8
滚动速度太慢了,让我感到很不爽。 - Bart Burg
3
那是一个用户界面的噩梦……我建议永远不要在这类事情上劫持滚动事件。用户期望一件事情,而你正在做另一件事情。 - AndrewMcLagan
3
我知道这个回答相当老了,但不能过分强调这是多么糟糕的想法。永远不要去改动原生功能。 - Tyler Kelley
这个有点小故障。 - godblessstrawberry
嗨,大家好,事情肯定会改变。我不知道我或我的团队中的任何人认为劫持和更改预期行为是个好主意。每当我回去维护这些网站之一时,我立刻对滚动行为感到厌恶:p - Kenny Bones

2
使用鼠标滚轮滚动需要特殊处理。原因是每次鼠标滚轮滚动并不会将内容滚动一定数量的像素。每次滚动都会导致页面跳动,而每个跳动都会导致“抖动”动画,因为背景图像正在尝试在这些跳动中定位自己。
使用库通常可以解决问题,但也值得了解它在底层试图解决什么问题。
仅供参考,鼠标事件为mousewheelDOMMouseScroll

1
这个Chrome插件提供了必要的功能。有人创建了一个它的压缩版本。它来自一个相当古老的版本,但我认为这没关系,因为我已经检查过,最新版本的插件添加了太多东西。

不过,那个代码片段有几个问题:

  • 它在启动之前会检查浏览器是否是Chrome。
  • 它会自动启动。
  • 它使用jQuery。

所以我创建了一个版本来解决这些问题。只需添加脚本并调用SmoothScroll.init()即可开始。


0

编辑:测试时我发现这个程序有一个重大的漏洞。虽然我的版本比原始代码表现得更好(在我看来),但它不幸地没有考虑到其他滚动方式(滚动条/中键拖动)。用其中一种方法滚动,然后用鼠标滚轮滚动会导致它恢复到你上次滚动鼠标滚轮时的滚动位置。我将在开发解决方案时进行更新。

Kenny提供的解决方案是一个很好的方法,但它的功能让我抓狂。如果你快速滚动鼠标滚轮,它不会滚动得更快。

我改进了它,使得每次点击都可以滚动给定的距离,而不管鼠标滚轮的旋转速度如何。

他的答案之所以不行,是因为如果在第一次动画完成之前再次滚动鼠标滚轮,新的滚动高度只是当前滚动高度加上每次滚轮点击滚动的距离。(所以如果滚动时间为0.5秒,你在0.25秒后第二次滚动,那么它将滚动1.5倍的滚轮滚动距离,而不是2倍的距离)

现在已经很晚了,希望这有意义。

无论如何,这是我的代码:

所需库

<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/ScrollToPlugin.min.js"></script>

滚动代码

<script>
    $(function(){   
        var $window = $(window)
        var $scoll = $('#page-container')
        var scrollTime = 0.5
        var scrollDistance = 120

        var scrollTop = $scoll.scrollTop()

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

            event.preventDefault()  

            var delta = event.originalEvent.wheelDelta/120 || -event.originalEvent.detail/3
            scrollTop = scrollTop - parseInt(delta*scrollDistance)
            scrollTop = Math.max(0, Math.min($scoll[0].scrollHeight, scrollTop))

            TweenMax.to($scoll, scrollTime, {
                scrollTo : { y: scrollTop, autoKill:true },
                    ease: Power1.easeOut,
                    overwrite: 5                            
                })

        })
    })
</script>

如果您希望使用原始代码,我建议减少动画时间。这样可以让您以更好的速度滚动,即使它仍然存在“损失”滚动距离。 - csga5000

0

好问题。

我使用的库是这个: https://github.com/cferdinandi/smooth-scroll

只需包含smoothscroll.js文件,工作就完成了。 现在,鼠标滚轮会平稳地向下滑动页面,而不是以像素块跳下去。

它真的可以改善视差网页的外观。

顺便说一句,对于视差图像,我使用这个库:

https://github.com/pederan/Parallax-ImageScroll

将此库包含并初始化在网页底部,图像和HTML之后,非常容易添加到网页中。

(我没有意识到这会有所不同,但它确实有!)


0

我知道我来晚了,但今天在偶然发现I Love me Wellness网站后,我开始研究平滑滚动的主题。 分析该网站的JavaScript代码,我发现他们使用了一个名为Luxy.js的vanillaJS脚本,该脚本在GitHub上展示Luxy.js。我觉得这种效果非常令人愉悦。如果实现得好,我认为这不是一个坏主意。而且它非常容易实现。


这不是一个答案,请将其添加到评论中。 - pullidea-dev
我不能@Nikita,因为我没有50个声望值:( - bistromatic

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