代码之家  ›  专栏  ›  技术社区  ›  chris

移动Safari上的粘性元素问题

  •  0
  • chris  · 技术社区  · 6 年前

    我有一个元素,当向下滚动时,我希望它一直在页面的顶部。在功能上,所有的代码都可以工作,这要感谢其他用户的支持。然而,当向下滚动手机时,粘性元素似乎落后了一点。我的意思是,每次父元素滚动时,代码似乎都在调用,它会对粘性元素进行成百上千的调整,从而使其稍微晃动。

    下面是代码:

    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 回复  |  直到 6 年前
        1
  •  0
  •   Oleg G    6 年前

    国际海事组织,一个可能和更有效的解决办法是 position: sticky 在CSS而不是JS中。你需要提供 top: 0 也。有些兼容性在IE中是滞后的,但它已经是一个可行的解决方案。值得一看 out here

    如果您担心旧的浏览器,可以在JS中添加一个回退函数,这仍然有点滞后。

        2
  •  0
  •   Sampson Crowley    6 年前

    你需要做的是 throttle debounce 更新元素的调用。

    另外,为什么要将滚动侦听器附加到 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)