【问题标题】:Do action once on multiple scroll events and prevent scrolling对多个滚动事件执行一次操作并防止滚动
【发布时间】:2014-12-14 01:50:25
【问题描述】:

我希望实现像 Google Inbox landing page 这样的滚动功能:

值得注意的是,无论您滚动滚轮的速度或次数,它都将计为“一”并进入下一步。这似乎说起来容易做起来难,因为没有办法取消“滚动”事件。有一种方法可以取消 DOMMouseScrollmousewheel 事件,但是这样做很棘手:

问题是取消这些事件的方式如下使用return preventFn(ev)

   var preventFn = function (ev) {
      ev.returnValue = false;
      return false;
   };

Try it here

但是,这样做会导致 scrollTop() 操作中断。但是没有它,滚动事件也会通过并弄乱它。

使用超时(参见小提琴),我可以通过一个相当错误的实现做得更好。它工作正常,但有一个主要错误是,如果用户在 scrollTop() 动画发生时滚动,一切都会永久中断。

我该如何纠正这个问题,让它像 Google 一样出色? (最好没有超时。在 Google 页面中,从第 3 步到第 4 步……我什至感觉不到任何超时,当我的鼠标滚轮开始移动时,它似乎立即滚动。所以这似乎是可能的)

【问题讨论】:

    标签: javascript jquery angularjs scroll


    【解决方案1】:

    似乎解决方案意味着使用锚点和超时。 灵感来自this post
    我已经更新了你的 plunkr。这是一个链接:http://plnkr.co/edit/GDdm7Z4OEzfh7ZwnQce7?p=preview

        app.directive('autoScroll', function($document, $timeout) {
        return {
            restrict: 'AE',
            link: function(scope, elem, attrs) {
                var delay = false;
                $document.on('mousewheel DOMMouseScroll', function(e) {
                    e.preventDefault();
                    if (delay) return;
    
                    delay = true;
                    $timeout(function() {
                        delay = false
                    }, 100)
    
                    var wd = e.originalEvent.wheelDelta || -e.originalEvent.detail;
    
                    var a = angular.element('a');
                    if (wd < 0) {
                        for (var i = 0; i < a.length; i++) {
                            var t = a[i].getClientRects()[0].top;
                            if (t >= 40) break;
                        }
                    } else {
                        for (var i = a.length - 1; i >= 0; i--) {
                            var t = a[i].getClientRects()[0].top;
                            if (t < -20) break;
                        }
                    }
                    angular.element('html,body').animate({
                        scrollTop: a[i].offsetTop
                    }, 500);
                });
            }
        }
    });
    

    【讨论】:

    • 嘿,我将如何在那里获得触控支持?如果您添加,我肯定会在 2 天内奖励赏金
    • 我一直在玩一些代码(它可以工作,但不像预期的那样;我一直在使用移动仿真模式使用开发工具对其进行测试)。这是fiddle 示例(不幸的是,目前 plunkr 无法正常工作)。你可以尝试改进它。今天下午 6 点(格林威治标准时间 +2)之后,我也可以返回到示例
    【解决方案2】:

    如果你想创建一个类似的网站,如果你还没有尝试过,我建议你使用fullPage.js

    关于超时问题,处理起来没那么简单。 Mac OS X 设备和 Apple 触控板或 Magic Mouse 具有相当大的惯性,即使在您停止滚动后 1 秒也会记录滚动事件。

    我会在 Mac 上尝试 Google 网站,看看它的反应如何,但同时我建议您仔细阅读我找到的解决问题的方法: stopping mousewheel event from happening twice in OSX

    【讨论】:

      【解决方案3】:

      使用纯 jquery: html:

         <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js">      </script>
      <body>
       <main> 
          <div class="contslide">Liza1</div>
          <div class="contslide">Liza2</div>
          <div class="contslide">Liza3</div>
          <div class="contslide">Liza4</div>
          <div class="contslide">Liza5</div>
       </main>
       </body>
      

      css:

        body{width:100%;height:100%;  overflow:hidden; margin:0px;}
        main{ position:absolute; width:100%;  height:100%;  font:20pt verdana;} 
        main div{width:100%;  height:100%; }
        main div:nth-child(odd) {background: #ff0000;}
      

      jquery:

        $(document).ready(function () {
        var delay = false;
        $(document).on('mousewheel DOMMouseScroll', function(event) {
          event.preventDefault();
          if(delay) return;
      
          delay = true;
          setTimeout(function(){delay = false},200)
      
          var wd = event.originalEvent.wheelDelta || -event.originalEvent.detail;
      
          var a= document.getElementsByClassName('contslide');
          if(wd < 0) {
            for(var i = 0 ; i < a.length ; i++) {
              var t = a[i].getClientRects()[0].top;
              if(t >= 40) break;
            }
          }
          else {
            for(var i = a.length-1 ; i >= 0 ; i--) {
              var t = a[i].getClientRects()[0].top;
              if(t < -20) break;
            }
          }
         $('html, body').animate({
          scrollTop: a[i].offsetTop
         });
         });
        });
      

      这是fiddle 示例

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-30
        • 2017-07-14
        • 2017-04-20
        • 2018-07-22
        • 1970-01-01
        相关资源
        最近更新 更多