【问题标题】:How can I "snap" scroll to the nearest predefined position?如何“捕捉”滚动到最近的预定义位置?
【发布时间】:2022-01-04 23:37:29
【问题描述】:

我有一个网站,它本质上是四个 div - 每个都设置为窗口的高度,因此总文档是窗口高度的四倍。

这个想法是点击一个 div 将滚动推进一个“窗口高度” - 效果很好,如下所示:

// on click event

if(cur_frame<number_slides){
   scrolling = true;
   $('html,body').animate({scrollTop:window_height*cur_frame},function(){
      scrolling=false;
   });
}

然而,在用户手动滚动页面后,我想将位置“捕捉”到最接近的窗口高度倍数 - 因此给定的 div 再次位于屏幕中心。我尝试使用超时,认为一个小的延迟会阻止它每秒触发一千次......

// on scroll event

clearTimeout(scroll_timer);
if(!scrolling) scroll_timer = setTimeout(function(){
   if(cur_scroll!=window_height*(cur_frame-1)) {
      scrolling = true;
      $('html,body').stop().animate({scrollTop:window_height*(cur_frame-1)},function(){
         scrolling = false;
      });
   }
},100); //20? 400? 1000?

...但无法在脚本与用户在滚动位置上发生争执,或严重的长时间延迟破坏“捕捉”效果之间取得平衡。

有什么建议可以实现吗?

【问题讨论】:

    标签: javascript jquery scroll


    【解决方案1】:

    用于此的 jquery scrollsnap 插件支持到 IE9。

    您要查找的内容称为“Scroll Snap”。

    <script src="demo/foundation/javascripts/jquery.js"></script>
    <script src="src/jquery.event.special.js"></script>
    <script src="src/jquery.easing.min.js"></script>
    <script src="src/jquery.scrollsnap.js"></script>
    <script type="text/javascript">
    $(document).ready(function() {
        $(document).scrollsnap({
            snaps: '.snap',
            proximity: 50
        });
    });
    </script>
    

    【讨论】:

    • 那些 jQuery 插件通常是用户体验杀手。
    【解决方案2】:

    有一个 CSS 规范,它很好地支持原生渲染和非常好的触摸行为,除了 Chrome:http://caniuse.com/#feat=css-snappoints

    对于落后的浏览器,有一个 polypill:https://github.com/ckrack/scrollsnap-polyfill

    另见How to emulate CSS Scroll Snap Points in Chrome?

    【讨论】:

      【解决方案3】:

      使用简单的scrollTo 怎么样?使用纯 Javascript 和 CSS,没有框架或库。

      这里有两个例子,一个用于垂直滚动,另一个用于水平滚动:

      最佳
      未知0wn0x

      【讨论】:

        【解决方案4】:

        如果您想考虑跨浏览器 javascript 重新实现原生 CSS Scroll Snap 规范,如已在此处回答:How to emulate CSS Scroll Snap Points in Chrome?,您可以使用 this library

        使用它而不是原生 css 解决方案的主要原因是它适用于所有现代浏览器,并且具有可自定义的配置,以允许在转换和滚动检测中自定义时间。

        该库使用原生 javascript 缓动函数重新实现 css 捕捉功能,并使用容器元素的 scrollTop/scrollLeft 属性值和 scroll 事件侦听器

        这是一个展示如何使用它的示例:

        import createScrollSnap from 'scroll-snap'
        
        const element = document.getElementById('container')
        
        const { bind, unbind } = createScrollSnap(element, {
          snapDestinationX: '0%',
          snapDestinationY: '90%',
          timeout: 100,
          duration: 300,
          threshold: 0.2,
          snapStop: false,
          easing: easeInOutQuad,
        }, () => console.log('snapped'))
        
        // remove the listener 
        // unbind();
        
        // re-instantiate the listener 
        // bind();
        

        【讨论】:

        • chrome 好像坏了,不能向下滚动,只能跳回顶部
        • @Steve 你用的是什么配置?我无法复制该问题(我使用的是 Chrome 67),您在 this demo page 上滚动是否有同样的问题?
        • Ubuntu 16.04 上的 Chrome 67 - 仅尝试了演示页面。似乎在 chrome 67 windows 10 上工作正常
        【解决方案5】:

        您可以使用 javascript 来执行此操作,或者对于稍微简单和较旧的解决方案,您可以使用页面锚点。 如果您将 document.location.hash 更改为页面中存在的锚点,则浏览器将滚动到它。 因此,在您的 HTML 中,在页面中放置一些锚点:

        <a name="anchor1" id="anchor1"></a>
        

        然后在你的 js 中放:

        document.location.hash = "anchor1";
        

        【讨论】:

        • 一个问题......页面锚点真的没有“滚动”。
        • 页面锚点的全部意义在于捕捉到一个位置!它确实有效,我在发布答案之前在 FF Chrome 和 IE 中尝试过,只是为了确定。不敢相信我因此而被否决!
        • 我相信 OP 要求的是“量化”效果。一旦用户完成滚动,浏览器就会平滑地将滚动位置“量化”到最近的滚动间隔。这就像“对齐网格”效果。
        • 哦,是的,我不敢相信我没有注意到这一点。对不起艾萨克。但你永远不会知道,有人可能会来到这个页面,寻找一种简单的方式在页面内导航并发现这个答案很有用,所以我会把它留在那里以供后代使用。
        • 嘿,谢谢,2019 年,它正在工作,不知道为什么这个答案是 -2,我猜他们不知道他们在说什么,我只是尝试过,它完成了工作 :)跨度>
        猜你喜欢
        • 1970-01-01
        • 2010-12-01
        • 1970-01-01
        • 2014-10-08
        • 1970-01-01
        • 1970-01-01
        • 2016-03-02
        • 2011-06-15
        • 1970-01-01
        相关资源
        最近更新 更多