Javascript 阻止鼠标滚轮事件在OSX中发生两次

Javascript 阻止鼠标滚轮事件在OSX中发生两次,javascript,jquery,macos,scroll,Javascript,Jquery,Macos,Scroll,我注意到鼠标滚轮事件在MacOSX中多次发生。可归因于惯性特性 有没有办法纠正这种行为 (请不要担心 我正在使用scrollSections.js 它使用mousewheel jquery插件: 我看到很多人都有同样的问题: 有一些解决方案,但没有一个能与scrollSections插件配合使用 你知道如何从JS中禁用这个惯性特性吗 我尝试的修复: // Fix for OSX inertia problem, jumping sections issue. if (isMac) { v

我注意到鼠标滚轮事件在MacOSX中多次发生。可归因于惯性特性

有没有办法纠正这种行为

(请不要担心

我正在使用scrollSections.js

它使用mousewheel jquery插件:

我看到很多人都有同样的问题:

有一些解决方案,但没有一个能与scrollSections插件配合使用

你知道如何从JS中禁用这个惯性特性吗

我尝试的修复:

// Fix for OSX inertia problem, jumping sections issue.
if (isMac) {

  var fireEvent;
  var newDelta = deltaY;

  if (oldDelta != null) {

    //check to see if they differ directions
    if (oldDelta < 0 && newDelta > 0) {
      fireEvent = true;
    }

    //check to see if they differ directions
    if (oldDelta > 0 && newDelta < 0) {
      fireEvent = true;
    }

    //check to see if they are the same direction
    if (oldDelta > 0 && newDelta > 0) {

      //check to see if the new is higher
      if (oldDelta < newDelta) {
        fireEvent = true;
      } else {
        fireEvent = false;
      }
    }

    //check to see if they are the same direction
    if (oldDelta < 0 && newDelta < 0) {

      //check to see if the new is lower
      if (oldDelta > newDelta) {
        fireEvent = true;
      } else {
        fireEvent = false;
      }
    }

  } else {

    fireEvent = true;

  }

  oldDelta = newDelta;

} else {

  fireEvent = true;

}
//修复OSX惯性问题、跳跃部分问题。
国际单项体育联合会(isMac){
var-firevent;
var newDelta=三角洲;
if(oldDelta!=null){
//检查它们是否有不同的方向
如果(旧增量<0&&新增量>0){
firevent=true;
}
//检查它们是否有不同的方向
if(oldDelta>0&&newDelta<0){
firevent=true;
}
//检查它们是否在同一方向
如果(旧增量>0&&新增量>0){
//检查新的是否更高
if(旧增量<新增量){
firevent=true;
}否则{
firevent=false;
}
}
//检查它们是否在同一方向
如果(旧增量<0&&新增量<0){
//检查新压力是否较低
如果(旧增量>新增量){
firevent=true;
}否则{
firevent=false;
}
}
}否则{
firevent=true;
}
oldDelta=newDelta;
}否则{
firevent=true;
}

您可以在这里看到已实现的修复程序:但这是一个成功的例子。

您是否考虑过使用? 它在到达某个区段和您能够滚动到下一区段的那一刻之间有一个延迟,该区段解决了Mac用户使用轨迹板或Apple magic Mous时遇到的部分问题


它还将为您提供一些其他好处,例如更多的选项、方法以及与触摸设备和不支持CSS3的旧浏览器的兼容性。

要想开始,让我们缩短您的解决方案(因此更易于理解和调试):

根据提供的代码,不清楚deltaY是如何计算的。可以假设,delta等于endPosition-initialPosition。因此,oldDelta>newDelta并不意味着新位置更低,而是意味着这两个值之间的新差距更大。如果这就是它的意思,而你仍然使用它,我想你应该试着用它来追踪惯性。然后您应该更改比较运算符(使用小于,而不是大于,反之亦然)。换句话说,我会写:

if(Math.abs(newDelta)>Math.abs(oldDelta)) return true; // (1.3) 
你看,现在我使用了“大于”操作符,这意味着:newDelta在绝对值上超过了olddeta=>这不是惯性,你仍然可以触发事件

这是你想要实现的还是我误解了你的代码?如果是这样,请通过比较新旧三角洲,说明如何计算三角洲,以及您的目标是什么。
另外,我建议在此步骤中不要使用if(isMac),因为问题也可能隐藏在那里。

你知道,我认为在这种情况下使用超时是一个更好的主意。为什么不这样写呢:

// Let's say it's a global context or whatever...:
var fireEvent = true;
var newDelta, oldDelta, eventTimeout;
newDelta = oldDelta = eventTimeout = null;

// ... and the function below fires onmousewheel or anything similar:
function someFunc(){
    if(!fireEvent) return; // if fireEvent is not allowed => stop execution here ('return' keyword stops execution of the function), else, execute code below:
    newDelta = deltaY;
    if(oldDelta!=null&&oldDelta*newDelta>0){ // (1.1) if it's not the first event and directions are the same => prevent possible dublicates for further 50ms:
        fireEvent = false;
        clearTimeout(eventTimeout); // clear previous timeouts. Important!
        eventTimeout = setTimeout(function(){fireEvent = true},500);
    }
    oldDelta = newDelta;
    someEventCallback(); // (1.2) fire further functions...
    }
因此,如果在上一次鼠标滚轮事件调用后的半秒钟内触发任何鼠标滚轮事件,且其方向与上一次相同(请参见第1.1节的条件),则将忽略该事件。这将解决问题,用户无法发现此问题。延迟量可能会更改,以更好地满足您的需要

该解决方案基于纯JS。欢迎您询问有关在您的环境中集成it的任何问题,但我需要您提供页面的进一步代码

另外,我在您的代码中没有看到类似于eventCallback()调用的东西(请参阅我的解决方案的1.2)。只有fireEvent标志。你是不是在做这样的事情:

if(fireEvent)
    someEventCallback();
以后还是什么

p.p.S.注意,fireEvent应该在全局范围内,以便在这里使用setTimeout。如果不是,也很容易使其工作良好,但代码需要稍加修改。如果是你的情况,告诉我,我会帮你解决

更新


经过简短的搜索,我发现下划线的_debounce()函数中使用了类似的机制。请参阅下划线文档

最新的超时解决方案有一个主要缺点:动态滚动效果可能会持续很长时间(甚至1秒左右)。。。禁用滚动1-2秒并不是最好的决定

如承诺的,这里还有另一种方法

我们的目标是为one用户操作提供one响应,在本例中是滚动

什么是“一次滚动”?为了解决这个问题,假设“一次滚动”是一个事件,从页面开始移动到移动结束

动态滚动效果是通过将页面多次移动(例如,每20毫秒)一小段距离来实现的。这意味着我们的动态滚动由许多小的线性“滚动”组成

实验结果表明,这一“小卷曲”发生在170~18Ms的动态涡旋中间,在开始和结束时约为80-90MS。下面是一个简单的测试,我们可以设置该测试:

var oldD;
var f = function(){
    var d = new Date().getTime();
    if(typeof oldD !== 'undefined')
        console.log(d-oldD);
    oldD = d;
}
window.onscroll=f;
重要!每次发生此小滚动时,都会触发滚动事件。因此:

 window.onscroll = function(){console.log("i'm scrolling!")};
将在一个动态滚动期间发射15到20+次。顺便说一句,onscroll有很好的浏览器支持(请参阅),所以我们可以依赖它(除了触摸设备,我稍后会讨论这个问题)

有人可能会说,重新定义window.onscroll并不是设置事件侦听器的最佳方法。是的,我们鼓励您使用

 $(window).on('scroll',function(){...});
或者不管你喜欢什么,这不是问题的关键(我个人使用我自己编写的库)

因此,在onscroll事件的帮助下,我们可以可靠地判断页面的这一特定微小移动是否属于一个长期的亲属
 window.onscroll = function(){console.log("i'm scrolling!")};
 $(window).on('scroll',function(){...});
    var prevTime = new Date().getTime();
    var f = function(){
        var curTime = new Date().getTime();
        if(typeof prevTime !== 'undefined'){
            var timeDiff = curTime-prevTime;
            if(timeDiff>200)
                console.log('New kinetic scroll has started!');
        }
        prevTime = curTime;
    }
    window.onscroll=f;