【问题标题】:scroll then snap to top滚动然后捕捉到顶部
【发布时间】:2011-07-04 16:59:52
【问题描述】:

只是想知道是否有人知道如何重新创建我不久前看到的导航栏样式,我刚刚找到了我看到它的网站,但不确定他们是如何到达那里的。基本上希望它随着页面滚动然后锁定到顶部...

http://lesscss.org/

【问题讨论】:

    标签: javascript jquery positioning


    【解决方案1】:

    听起来像是 Jquery ScrollTop 的应用程序和导航栏元素的 CSS 属性的一些操作。例如,在某些滚动条件下,导航栏元素从计算坐标的绝对定位变为固定定位。

    http://api.jquery.com/scrollTop/

    【讨论】:

    • 老实说,我看了一下,发现没有办法将某些东西锁定在顶部。
    【解决方案2】:

    您描述的效果通常以某种类型的动画开始,例如 TheDeveloper 的回答。默认动画通常通过改变元素的位置来滑动元素,或者通过改变元素的不透明度等来淡入/淡出元素。

    获得“bouce back”或“snap to”效果通常涉及缓动。所有主要框架都有某种形式的缓动可用。这完全取决于个人喜好;任何一个你都不会出错。

    jQuery 有easing plugins,您可以将其与.animate() 函数一起使用,或者您可以使用jQueryUI

    MooTools 的核心库的 FX 类有 easing built in

    Yahoo 的 YUI 也有easing built in

    如果您能记住它是什么网站,您可以随时再次访问它并查看其来源以了解使用的框架和效果。

    【讨论】:

      【解决方案3】:

      只需在http://lesscss.org/ 上快速“查看源代码”,您就会看到:

      window.onscroll = function () {
          if (!docked && (menu.offsetTop - scrollTop() < 0)) {
              menu.style.top = 0;
              menu.style.position = 'fixed'; 
              menu.className = 'docked'; 
              docked = true;
          } else if (docked && scrollTop() <= init) { 
              menu.style.position = 'absolute'; 
              menu.style.top = init + 'px';
              menu.className = menu.className.replace('docked', ''); 
              docked = false;  
          }
      };
      

      它们绑定到窗口的onscroll 事件,该事件在窗口滚动时触发。当菜单“锁定”到页面顶部时,docked 标志设置为 true,同时该标志设置为 true,菜单设置为 position:fixed。剩下的只是一些简单的“我们要从页面上滚动菜单吗”和“我们要回到我们开始的地方了吗”位置检查逻辑。

      您必须小心onscroll 事件,它们可以快速连续触发很多,因此您的处理程序需要非常快并且应该尽可能地预先计算。

      在 jQuery 中,它看起来几乎相同:

      $(window).scroll(function() {
          // Pretty much the same as what's on lesscss.org
      });
      

      你经常看到这种“浮动几乎固定位置垂直工具栏”的东西,比如cracked.com上的东西。

      【讨论】:

      • 为什么要添加menu.className?这究竟是做什么的?
      • @user3272438:我没有补充,代码来自lesscss.org。我猜menu 是一个DOM 元素,所以menu.className 将是它的class 属性。
      • 我觉得没问题,因为我正在尝试实现相同的代码并且我决定不使用className.replace。我遇到的问题是,当它脱离时它不会向下滚动,它要么卡在顶部,要么与之前的 div 元素的顶部对齐。不知道你有没有什么想法。
      • @user3272438:我不知道你的代码是什么样的,也许可以用最小的可运行代码示例提出一个新问题。
      • 我确实发布了一个新问题,但这里是demo
      【解决方案4】:

      mu is too short answer is working,我只是发布这个给你 jquery 脚本!

      var docked = false;
      var menu = $('#menu');
      var init = menu.offset().top;
      
      $(window).scroll(function() 
      {       
              if (!docked && (menu.offset().top - $("body").scrollTop() < 0)) 
              {
                  menu.css({
                      position : "fixed",
                      top: 0,
                  });
                  docked = true;
              } 
              else if(docked && $("body").scrollTop() <= init)
              {
                  menu.css({
                      position : "absolute",
                      top: init + 'px',
                  });
      
                  docked = false;
              }
      });
      

      【讨论】:

        【解决方案5】:

        穆的回答让我走得很远。我尝试了 replicationg lesscss.org 的方法,但遇到了关于浏览器调整大小和缩放的问题。我花了一段时间才知道如何正确应对以及如何重置初始位置 (@987654323 @) 没有 jQuery 或任何其他库。

        在 JSFiddle 上查找预览: http://jsfiddle.net/ctietze/zeasg/

        这里是详细的纯 JavaScript 代码,以防 JSFiddle 拒绝工作。


        可重复使用的滚动然后捕捉菜单类

        这是一个可重复使用的版本。我将滚动检查放入一个类中,因为所涉及的辅助方法使我的主命名空间变得混乱:

        var windowScrollTop = function () {
          return window.pageYOffset;
        };
        
        var Menu = (function (scrollOffset) {
          var Menu = function () {
            this.element = document.getElementById('nav');
            this.docked = false;
            this.initialOffsetTop = 0;
        
            this.resetInitialOffsetTop();
          }
        
          Menu.prototype = {
            offsetTop: function () {
              return this.element.offsetTop;
            },
            resetInitialOffsetTop: function () {
              this.initialOffsetTop = this.offsetTop();
            },
        
            dock: function () {
              this.element.className = 'docked'; 
              this.docked = true;
            },
            undock: function () {
              this.element.className = this.element.className.replace('docked', ''); 
              this.docked = false;
            },
        
            toggleDock: function () {
              if (this.docked === false && (this.offsetTop() - scrollOffset() < 0)) {
                this.dock();
              } else if (this.docked === true && (scrollOffset() <= this.initialOffsetTop)) { 
                this.undock();
              }
            }
          };
        
          return Menu;
        })(windowScrollTop);
        
        
        var menu = new Menu();
        
        
        window.onscroll = function () {
          menu.toggleDock();
        };
        

        处理缩放/页面调整大小事件

        var updateMenuTop = function () {
          // Shortly dock to reset the initial Y-offset
          menu.undock();
          menu.resetInitialOffsetTop();
        
          // If appropriate, undock again based on the new value
          menu.toggleDock();
        };
        
        var zoomListeners = [updateMenuTop];
        
        (function(){
          var w = window,
              d = document,
              e = d.documentElement,
              g = d.getElementsByTagName('body')[0];
        
          var lastWidth = 0;
        
          function pollZoomFireEvent() {
            var widthNow = w.innerWidth || e.clientWidth || g.clientWidth;
        
            if (lastWidth == widthNow) {
              return;
            }
        
            lastWidth = widthNow;
        
            // Length changed, user must have zoomed, invoke listeners.
            for (i = zoomListeners.length - 1; i >= 0; --i) {
              zoomListeners[i]();
            }
          }
        
          setInterval(pollZoomFireEvent, 100);
        })();
        

        【讨论】:

        • 我喜欢你的代码,我很好奇它是否像一个带有菜单的插件。(元素,目标),scrollOffset代表什么,似乎删除它会在dockToggle上引发一些讨厌的错误,那又如何你有什么建议?
        • scrollOffset() 是 Menu 初始化时注入的属性(仅参数)。在这种情况下,它只是通过引用传入windowScrollTop。我这样做是为了将菜单与window.pageYOffset 分离,即使我认为没有其他方法可以应用。所以你也可以将scrollOffset作为方法添加到Menu,直接包装window.pageYOffset
        • 谢谢,我设法把它变成了一个带有选项的很棒的插件,就像 Bootstrap Affix 一样,实际上它会成为它的替代品。您有兴趣合作转换更多 BS 插件吗?
        • 酷。我不能说我有太多的空闲时间。但也许我可以不时使用一些练习。给我留言,告诉我插件是什么样子的。电子邮件在我的个人资料中。
        • 你去吧,随意分叉、贡献和/或组队。 github.com/thednp/Bootrstrap-Vanilla-JS
        猜你喜欢
        • 2016-09-13
        • 2019-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-25
        • 1970-01-01
        • 2018-03-27
        • 1970-01-01
        相关资源
        最近更新 更多