根据屏幕高度隐藏DIV并进行去抖动

时间:2014-01-30 00:18:55

标签: javascript jquery html debouncing

我正在开发一个页面,其中包含一个固定位置的简单侧导航,顶部设置为:30%。我需要发生的是在页面的底部我想淡出菜单,所以它不会与页脚重叠,下面的代码可以工作,但我认为这是检查滚动这么多,你要花很长时间来计算向下滚动。

是否有更快/更轻量级的方法来计算何时隐藏侧导航?我不熟悉去抖动但它有帮助吗?

元素:

.body-container-wrapper - total height of page
.footer-container-wrapper - total height of the footer that we want the nav to be hidden at
.internal-side-nav - the menu position: fixed, top: 30%, right: 0

示例页面:http://hsb1.hubspot.com/profile-page-template

脚本:

<script type="text/javascript">
$(document).scroll(function () {
   var y = $(this).scrollTop();
   if (y < $('.body-container-wrapper').outerHeight() - $('.footer-container-   wrapper').outerHeight() - 400 ) {
    $('.internal-side-nav').fadeIn();
 } else {
    $('.internal-side-nav').fadeOut();
 }
});
</script>

2 个答案:

答案 0 :(得分:0)

我没有听说过去抖,所以我不得不查阅它。它可能有所帮助,但这将是一个额外的插件,你必须包括和维护,它可能无法正常工作你想要的(我没有看到任何表明它确实“束或时间框架”,只是似乎是束,这意味着它可能会在你身后发射。)

相反,你可以做的就是用一点时间自己节约它。

var scrollTimeInterval = 200; // how often we allow the action to trigger, in ms.
var lastScrollTime = 0;
var scrollTimeoutId = null;
$(document).scroll(function () {
   var now = (new Date()).getTime();
   var dScrollTime = now - lastScrollTime;
   lastScrollTime = now;

   if (dScrollTime < scrollTimeInterval) {
        // Set a timeout so we catch the last one.
        scrollTimeoutId = setTimeout(function() { $(document).scroll(); }, scrollTimeInterval - dScrollTime);
        return; // too soon, so we'll skip
   }

   // Clear any potentially pending timeout.
   clearTimeout(scrollTimeoutId);

   var y = $(this).scrollTop();
   if (y < $('.body-container-wrapper').outerHeight() - $('.footer-container-   wrapper').outerHeight() - 400 ) {
    $('.internal-side-nav').fadeIn();
 } else {
    $('.internal-side-nav').fadeOut();
 }
});

这样,如果滚动事件自上次触发以来还没有达到一定的时间,那么它就不会做任何事情。为了确保我们捕获最后一个滚动事件(它们停止滚动之前的最后一个),我添加了一个超时,它将最后一次触发滚动事件。我们还必须确保清除,如果我们在它发生之前处理另一个滚动事件(所以我们不会加倍)。

您可以使用第一个变量控制它允许的时间间隔。如果200ms感觉有点迟钝,你可以把它减少到100ms或50ms,看看是否能提供更好的平衡。

希望有所帮助。

答案 1 :(得分:0)

处理滚动事件,在某些情况下,你无能为力。

解决方案1:在每次迭代时取消自身的setTimeout

我认为这种方法效率最高,但对你来说可能不太理想,因为在它消失之前,sidenav在视觉上会重叠页脚,因此仍然会有300ms。

var scrollTimeout = false;
$(document).scroll(function(){
  clearTimeout(scrollTimeout);
  var _this = this; // for the setTimeout function to know what "this" is
  scrollTimeout = setTimeout(function(){
    // your original code block goes here
    // BUT, replace "this" with "_this"
  }, 300);
});

以上基本上只在用户未滚动至少300毫秒时运行您的代码。

解决方案2:只是旧的优化(不是太多技巧)

此解决方案应立即隐藏sidenav,但仍会在每个滚动上运行,只需少量

var myScrollEvent = (function(){
  var $win = $(window);
  var $foot = $('.footer-container-wrapper');
  var footer_top = $foot.offset().top; // where on the page the footer begins
  var $nav = $('.internal-side-nav');
  var nav_height = $nav.height(); // maybe use outerHeight(true)?...who knows, only you
  var is_hidden = false;

  // this is the actual function we want to run on-scroll
  return function(){
    // jquery, even on fixed elements, still seems to account for scroll position
    // when calculating top offset value, below is the coordinate of the bottom of the nav
    var nav_bottom = $nav.offset().top + nav_height;

    // if the bottom coord of the nav is lower than the top coord of the footer
    if(nav_bottom > footer_top && !is_hidden){
      is_hidden = true;
      // hide it code
    }else if(is_hidden){
      is_hidden = false;
      // show it code
    }
  };

})();

$(window).scroll(myScrollEvent);

这里的想法是缓存一些变量,并以稍微不同的方式进行计算。你的方式似乎没有任何错误,但这只是一个选择。请注意,使用此方法,我们假设导航高度永远不会改变。

如果您愿意,也可以随时将这两种解决方案结合起来。

另外,请注意我没有进行任何浏览器2浏览器测试,所以如果有任何缺陷,请告诉我。