移动野生动物园中的粘性元素问题

时间:2018-10-02 21:07:45

标签: javascript html css

我有一个元素,向下滚动时希望保留在页面顶部。从功能上讲,所有代码都能正常工作,这要归功于SO上的另一个用户。但是,在手机上向下滚动时,粘性元素似乎滞后了一点。我的意思是,每次父元素滚动时,代码似乎都会调用一次,这会导致对粘性元素进行数百或数千次调整,从而使它有些动摇。

这是下面的代码:

HTML

<div id="scroller-wrapper">
  <div id="scroller-anchor"></div> 
  <div id="scroller" class="row visible-xs-block meal-controls">
     My sticky element is here and working   
  </div> 
</div>

JS

    $('#scroller-wrapper').scroll(function() {
      var $anchor = $("#scroller-anchor");
      var $scroller = $('#scroller'); 
      var move = function() {
        var st = $(window).scrollTop();
        var ot = $anchor.offset().top;
        if(st > ot) { 
          $scroller.addClass('fixedElement');
        } else {
          $scroller.removeClass('fixedElement');
        }
    };
    $(window).scroll(move);
    move();
});

CSS

.fixedElement {
  position:fixed;
  top:0;
  right:0;
  width:100%;
  z-index:10000;
}

2 个答案:

答案 0 :(得分:0)

您需要做的是throttledebounce调用以更新元素。

为什么还要在包装滚动处理程序内部将滚动侦听器附加到window?这意味着每次调用滚动侦听器时,都会将另一个滚动侦听器附加到window

您需要的只是窗口上的单个处理程序,并允许传播来完成其余的操作。

// A debounce function wraps a function with a setTimeout,
// and then resets that timeout everytime it is called

function debounce(func, delay){
  var timeout, that = this;

  delay = delay || 300;

  return function() {
    if(timeout) clearTimeout(timeout)
    timeout = setTimeout(function() {
      return func.apply(that, arguments)
    }, delay)
  }
}

// a throttle function ensures that a function isn't
// called more than once every interval

function throttle(fn, interval, shouldDebounce){
  var lastCall = 0, debouncedFn;

  interval = interval || 300

  if(shouldDebounce) debouncedFn = debounce(fn, interval);

  return function(){
    var now = (new Date()).getTime();
    if(now - lastCall < interval)
      return debouncedFn && debouncedFn.apply(this, arguments);

    lastCall = now;
    return fn.apply(this, arguments);
  }
}

// create a function to set scroll listeners
function setScroller() {
  var $anchor = $("#scroller-anchor"),
      $scroller = $('#scroller'),
      onMove = function onMove() {
        var st = $(window).scrollTop(),
            ot = $anchor.offset().top;

        if(st > ot) { 
          $scroller.addClass('fixedElement');
        } else {
          $scroller.removeClass('fixedElement');
        }
      },
      // Throttle the onMove function to make sure it isn't called too often
      throttlededOnMove = throttle(onMove, 300);

  $(window).scroll(throttlededOnMove);
}

// attach scroll listener on document ready
$(setScroller)

答案 1 :(得分:0)

IMO,一种可能且更有效的解决方案是在CSS中使用position: sticky,而不是JS。您还需要提供top: 0。 IE中的某些兼容性落后,但它已经是可行的解决方案。值得检查out here

如果您担心旧的浏览器,可以在JS中添加一个后备功能,该功能仍然有些落后