在OSX中停止鼠标轮事件发生两次 [英] stopping mousewheel event from happening twice in OSX

查看:159
本文介绍了在OSX中停止鼠标轮事件发生两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到鼠标轮事件在mac osx中多次发生。可以归因于惯性特征。

I noticed mousewheel event is happening multiple times in mac osx. Can be atributed to inertia feature.

有没有办法解决这个问题?

Is there a way to fix this behaviour?

(自签名的ssl不用担心!)
https://sandbox.idev.ge/roomshotel/html5_v2/

(self signed ssl no worries please!) https://sandbox.idev.ge/roomshotel/html5_v2/

我正在使用scrollSections.js https://github.com/guins/jQuery.scrollSections

I'm using scrollSections.js https://github.com/guins/jQuery.scrollSections

它使用mousewheel jquery插件: https://github.com/brandonaaron/jquery-mousewheel

And it uses mousewheel jquery plugin: https://github.com/brandonaaron/jquery-mousewheel

I看到很多人遇到同样的问题: https://github.com/ brandonaaron / jquery-mousewheel / issues / 36

I'm seeing a lot of people having the same issue: https://github.com/brandonaaron/jquery-mousewheel/issues/36

有一些解决方案但滚动截面插件无效。

There are some solutions but none works with scrollSections plugin.

任何我deas如何从JS中禁用此惯性功能?

Any ideas how to disable this inertia feature from 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;

}

您可以在此处看到修复: https://sandbox.idev.ge/roomshotel/html5_v2/ 但这是热门/未命中。

You can see fix implemented here: https://sandbox.idev.ge/roomshotel/html5_v2/ But it is a hit/miss.

推荐答案

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

The latest solution with timeouts had one major drawback: kinetic scrolling effect could last rather long (even 1s or so)... and disabling scrolling for 1-2 seconds wouldn't be the best decision.

Soooo,正如所承诺的,这是另一种方法。

Soooo, as promised, here's another approach.

我们的目标是为一个用户操作提供一个响应,在这种情况下是滚动。

Our goal is to provide one response for one user action, which in this case is scrolling.

什么是'一次滚动'?为了解决这个问题,让我们说'一次滚动'是一个持续的事件页面开始移动直到移动结束的那一刻

What's 'one scrolling'? For the sake of solving this problem, let's say that 'one scrolling' is an event that lasts from the moment the page has started to move till the moment the movement has ended.

动态滚动效果是通过多次移动页面(比方说,每隔20ms)一小段距离来实现的。这意味着我们的动力学滚动包含许多很小的线性滚动。

Kinetic scrolling effect is achieved by moving the page many times (say, every 20ms) for a small distance. It means that our kinetic scrolling consists of many-many little linear 'scrollings'.

经验测试表明,在动能滚动中间每17-18ms发生一次滚动,在开始和结束时约为80-90ms。以下是我们可以设置的简单测试:

Empirical testing has showed that this little 'scrollings' happen every 17-18ms in the middle of kinetic scroll, and about 80-90ms at the beginning and the end. Here's a simple test we can set up to see that:

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有很好的浏览器支持(参见兼容性表),所以我们可以依赖它(除了对于触摸设备,我稍后会讨论这个问题);

will be fired 15 to 20+ times during one kinetic scroll. BTW, onscroll has really good browser support (see compatibility table), so we can rely on it (except for touch devices, I'll cover this issue a bit later);

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

Some may say that redefining window.onscroll is not the best way to set event listeners. Yes, you're encouraged to use

 $(window).on('scroll',function(){...});

或者你喜欢什么,这不是问题的关键(我个人使用我自己编写的库)。

or whatever you like, it's not the point of the problem (I personally use my self-written library).

因此,在onscroll事件的帮助下,我们可以可靠地说出页面的这个特殊迷你运动是属于一个持久的动力学滚动,还是它一个新的:

So, with the help of onscroll event we can reliably say whether this particular mini-movement of the page belongs to one long-lasting kinetic scroll, or is it a new one:

    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;

您可以调用所需的回调函数(或事件处理程序)而不是console.log '重做!
这个函数只会在每个动能或简单滚动上被触发一次,这是我们的目标。

Instead of "console.log" you can call your desired callback function (or event handler) and you're done! The function will be fired only once on every kinetic or simple scroll, which was our goal.

您可能已经注意到我使用了200ms作为它是新卷轴还是前一卷轴的一部分的标准。您可以将其设置为更高的值,即999%,确保您可以阻止任何额外的呼叫。但是,请记住,我在之前的回答中使用了 NOT 。它只是两个页面移动之间的一段时间(无论是新卷轴还是动态卷轴的一小部分)。在我看来,动能滚动的步数之间的滞后时间可能会超过200毫秒(否则根本就不会平滑)。

You may have noticed that I've used 200ms as a criteria of whether it's a new scroll or a part of the previous scroll. It's up to you to set it to greater values to be 999% sure you prevent any extra calls. However, please keep in mind that it's NOT what we have used in my previous answer. It's just a period of time between any two page movements (whether it's a new scroll or a little part of a kinetic scroll). To my mind, there's a very little chance that there will be a lag more than 200ms between steps in kinetic scroll (otherwise it will be not smooth at all).

As我上面已经提到过,onscroll事件在触摸设备上的工作方式不同。在动能滚动的每一个小步骤中都不会发射。但是当页面的移动最终结束时它会触发。此外,还有ontouchmove活动......所以,这不是什么大不了的事。如有必要,我也可以为触摸设备提供解决方案。

As I've mentioned above, the onscroll event works differently on touch devices. It won't fire during every little step of kinetic scroll. But it will fire when the movement of the page has finally ended. Moreover, there's ontouchmove event... So, it's not a big deal. If necessary, I can provide solution for touch devices too.

P.S。我知道我写得太多了,所以如果你需要的话,我很乐意回答你的所有问题并提供更多代码

所有浏览器都支持所提供的解决方案,非常轻量级,更重要的是,它不仅适用于mac,而且适用于可能实现动态滚动的每个设备,所以我认为这真的是一种方法。

Provided solution is supported in all browsers, very lightweight and, what's more important, is suitable not only for macs, but for every device that might implement kinetic scrolling, so I think it's really a way to go.

这篇关于在OSX中停止鼠标轮事件发生两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆