如何"snap"滚动到最近的预定义位置?



我有一个网站,基本上是四个div - 每个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?

。但无法在脚本与用户争夺滚动位置或破坏"捕捉"效果的严重长时间延迟之间取得平衡。

有什么建议可以做到这一点吗?

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

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

另请参阅如何在 Chrome 中模拟 CSS 滚动对齐点?

jquery scrollsnap 插件支持低至 IE9。

您正在寻找的内容称为"滚动快照"。

<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>

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

下面是两个示例,一个用于垂直滚动,另一个用于水平滚动:

  • 垂直:https://jsfiddle.net/x9z5tpye/
  • 水平:https://jsfiddle.net/bwsyn6q4/

如果你想考虑跨浏览器的javascript重新实现原生的CSS Scroll Snap规范,正如这里已经回答的那样:如何在Chrome中模拟CSS滚动捕捉点?,你可以使用此库

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

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

下面是一个演示如何使用它的示例:

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

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

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

然后在您的 JS 中放置:

document.location.hash = "anchor1";

最新更新