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

使“ScrollLeft”/“ScrollTop”更改不触发滚动事件侦听器

  •  16
  • Matchu  · 技术社区  · 15 年前

    目前,我的程序在一个地方,它都在监听用户滚动某个元素,但有时也会自动滚动这个元素本身。(不是逐渐的,漂亮的卷轴,而是瞬间的跳跃。我发誓,这在上下文中是有意义的。)

    如果滚动是通过设置ScrollLeft或ScrollTop完成的,是否有方法使滚动事件不触发?我的第一个想法是一个基本的转换,比如:

    ignoreScrollEvents = true;
    element.scrollLeft = x;
    ignoreScrollEvents = false;
    
    function onScroll() {
      if(ignoreScrollEvents) return false;
    }
    

    但由于事件不会立即触发(哎呀,哎呀),这不是一个可行的解决方案。我还可以尝试其他哪种答案?如果有什么帮助的话,我也在使用jquery。

    5 回复  |  直到 7 年前
        1
  •  19
  •   Community Dunja Lalic    7 年前

    最简单的通用方法?只需重置事件处理程序中的标志。如果您真的要更改值,您需要首先检查,否则将不会激发事件-as Rodrigo notes ,这里的一个好做法是将其分解为所谓的“setter”函数:

    function setScrollLeft(x)
    {
      if ( element.scrollLeft != x )
      {
        ignoreScrollEvents = true;
        element.scrollLeft = x;
      }
    } 
    
    ...
    
    function onScroll() 
    {
      var ignore = ignoreScrollEvents;
      ignoreScrollEvents = false;
    
      if (ignore) return false;
    
      ...
    }
    

    但是,根据您的需要,您可能已经在某处存储了滚动位置;如果是,只需更新并检查它作为您的标志。类似:

    element.scrollLeft = currentScrollLeft = x;
    
    ...
    
    function onScroll() 
    {
      // retrieve element, etc... 
    
      if (element.scrollLeft == currentScrollLeft) return false;
    
      ...
    }
    
        2
  •  2
  •   vsync Qantas 94 Heavy    7 年前

    二传手怎么样?

    var _preventEvent = false; // set global flag 
    
    function setScrollTop(amount) {
      _preventEvent = true; // set flag
      document.documentElement.scrollTop = amount * Math.random();
    }
    
    function setScrollLeft(amount) {
      _preventEvent = true; // set flag
      document.documentElement.scrollLeft = amount * Math.random();
    }
    
    // scroll event listener
    window.onscroll = function() {
      console.clear();
      
      if (_preventEvent) {
        _preventEvent = false; // reset flag
        return;
      }
      
      console.log('normal scroll');
    }
    html{ height:500%; width:500%; } 
    button{ position:fixed; }
    button + button{ top:50px; }  
    <button onclick=setScrollTop(1000)>Random scrollTop</button>
    <button onclick=setScrollLeft(1000)>Random scrollLeft</button>
        3
  •  1
  •   marcgg    15 年前

    你可以 constantly check 如果 scroll position 变化。。。

        4
  •  0
  •   Colin    15 年前

    您可以尝试存储元素的偏移量顶部,并在进入OnScroll时将其与滚动条进行匹配:

    function onScroll(){
        var scrollTop = (document.documentElement.scrollTop || document.body.scrollTop),
        offsetTop = $('selector').offset().top;
        if(offsetTop > scrollTop){
          //user has not scrolled to element so do auto scrolling
        }
    }
    
        5
  •  0
  •   Matchu    15 年前

    好吧,我的最终解决方案,基于shog9构建(不是我真正的代码,而是我的方法):

    var oldScrollLeft = element.scrollLeft;
    element.scrollLeft = x;
    if(element.scrollLeft != oldScrollLeft) {
      ignoreScrollEvents = true;
    }
    
    function onScroll() {
      if(!ignoreScrollEvents) performGreatActions();
      ignoreScrollEvents = false;
    }
    

    if语句只在ScrollLeft值实际结束更改时设置ignore标志,因此从0到0的设置等情况不会错误地设置标志。

    谢谢大家!