【问题标题】:Scrollable Panel snap to elements on Scroll可滚动面板捕捉到 Scroll 上的元素
【发布时间】:2011-07-23 12:39:23
【问题描述】:

在可滚动的 div 中是否有一种方法可以在用户滚动时捕捉到元素。

例如,如果我们有 CSS 之类的

.container {
    height: 300px;
    width: 200px;
    overflow: auto
}
li {
    height: 40px;
    width: 100 % ;
}

和 HTML 一样

<div class="container">
    <li>
        test
    </li>
    <li>
        test
    </li>
    <li>
        test
    </li>
    <li>
        test
    </li>
    <li>
        test
    </li>
    <li>
        test
    </li>
    <li>
        test
    </li>
    <li>
        test
    </li>
    <li>
        test
    </li>
    <li>
        test
    </li>
    <li>
        test
    </li>
    <li>
        test
    </li>
    <li>
        test
    </li>
</div>

因此容器应该有一个垂直滚动条。当用户滚动时,我希望这样当他们停止滚动时,最终滚动位置会将容器滚动位置捕捉到所示最近的 div。这可能很困难,因为像 safari 这样的浏览器也提供动力,所以它必须是滚动结束时的事件。

任何想法,如果这是可能的,以及如何。

太棒了

【问题讨论】:

    标签: jquery css scroll


    【解决方案1】:

    您可以使用 setTimeout。这应该工作

    var snap_timer;
    var scroll_from_mouse = true;
    
    function snapList(){
      var snapped = false;
      var i = 0;
      while(!snapped && i < $('.container li').size()){
        var itop = $('.container li').eq(i).position().top;
        var iheight = $('.container li').eq(i).outerHeight();
        if(itop < iheight && itop > 0){ 
          scroll_from_mouse = false;
          snapped = true;
          var new_scroll_top = 0;
          if(iheight - itop > iheight / 2)
            new_scroll_top = $('.container').scrollTop() + itop;
          else if(i > 1)
            new_scroll_top = $('.container').scrollTop() - ($('.container li').eq(i-1).outerHeight() - itop);
          else
            new_scroll_top = 0;
          $('.container').scrollTop(new_scroll_top);
        }
        i++;
      }
    };
    
    $(function(){
      $('.container').scroll(function(){
        clearTimeout(snap_timer);
        if(scroll_from_mouse) snap_timer = setTimeout(snapList, 200);
        scroll_from_mouse = true;
      });
    });
    

    【讨论】:

    • 非常好。不过有点生涩。我正在尝试复制选择输入在 iPad 和 iPhone 上的工作方式。那是尽管您可以平滑地滚动它以捕捉到内部元素。你的功能很好,不要误会我只是一个完美主义者
    【解决方案2】:

    您可以使用CSS Scroll Snap

    但是,该功能现在已被弃用,因此如果您想考虑跨浏览器原生 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();
    

    你可以看到一个工作演示here

    【讨论】:

    • 如果您想推广或推荐自己的产品/博客,请注意,有一些guidelines in place 可以这样做。关注它们将帮助您避免给人留下垃圾邮件的印象。您能否编辑以明确说明您的隶属关系?谢谢。 (如果您实际上没有隶属关系,则可能也值得一提。)
    猜你喜欢
    • 2011-11-10
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多