New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

osx inertia #36

Open
annam opened this Issue Aug 14, 2012 · 67 comments

Comments

Projects
None yet
@annam

annam commented Aug 14, 2012

hi!

when using a trackpad or a magic mouse multiple events are triggered for every touch-scroll, sometimes taking as long as 1-2 seconds to stop, depending the scrolling "speed" and due to the inertia setting on mac osx.

I'm using mousewheel in a scenario where I move through news items on mousewheel and ideally I only want to move by on one each mousewheel action on windows, one each touch-scroll gesture on a mac trackpad.

The multiple events triggered make this impossible to do. I've tried unbinding and rebinding but as soon as I rebind the events triggered by the touch action before the unbind keep getting detected. I've tried filtering the delta to only scroll if it's between 2 values but its making the scroll very unreliable. Rebinding mousewheel only after the inertia events stop is also an impossibility because it would mean only allowing one scroll every two seconds.

do you have any ideas on how to overcome this?

@danro

This comment has been minimized.

Show comment
Hide comment
@danro

danro Aug 27, 2012

Underscore's debounce function is a good solution here.
http://documentcloud.github.com/underscore/#debounce

You would set up your callback passing the 'immediate' parameter like this:
myCallback = _.debounce(myCallback, 200, true);

danro commented Aug 27, 2012

Underscore's debounce function is a good solution here.
http://documentcloud.github.com/underscore/#debounce

You would set up your callback passing the 'immediate' parameter like this:
myCallback = _.debounce(myCallback, 200, true);

@alberto2000

This comment has been minimized.

Show comment
Hide comment
@alberto2000

alberto2000 Sep 11, 2012

I was having the exact same problem here. I've been trying to manipulate/lower the delta (by multiplying it with some negative threshold value) to achieve some "slower" scrolling and to deal with osx scroll inertia. Now looking into underscore's (actually using lo-dash.js) debounce function I was able to make the scrolling more controllable. Thanks for pointing that out!

alberto2000 commented Sep 11, 2012

I was having the exact same problem here. I've been trying to manipulate/lower the delta (by multiplying it with some negative threshold value) to achieve some "slower" scrolling and to deal with osx scroll inertia. Now looking into underscore's (actually using lo-dash.js) debounce function I was able to make the scrolling more controllable. Thanks for pointing that out!

@yoannmoinet

This comment has been minimized.

Show comment
Hide comment
@yoannmoinet

yoannmoinet May 22, 2013

I found out that the magic number here was 40.
Let me explain myself.
It seems that with the trackpad (probably with the magic mouse too) the delta get increased 40 times.
And it stays that way even if you take back your normal mouse and scroll with it later.
So what I did, simply :

b.mousewheel(function(evt,delta,deltaX,deltaY){
    if(Math.abs(deltaY)>=40)
        deltaY/=40;
    if(Math.abs(deltaX)>=40)
        deltaX/=40;

    //Do your stuff here.
});

yoannmoinet commented May 22, 2013

I found out that the magic number here was 40.
Let me explain myself.
It seems that with the trackpad (probably with the magic mouse too) the delta get increased 40 times.
And it stays that way even if you take back your normal mouse and scroll with it later.
So what I did, simply :

b.mousewheel(function(evt,delta,deltaX,deltaY){
    if(Math.abs(deltaY)>=40)
        deltaY/=40;
    if(Math.abs(deltaX)>=40)
        deltaX/=40;

    //Do your stuff here.
});
@DigitalWheelie

This comment has been minimized.

Show comment
Hide comment
@DigitalWheelie

DigitalWheelie Oct 8, 2013

Any recent, all-encompassing solution w/ the latest version, that will work when the Apple Magic Mouse is present, but also if not, on Windows, tablets and phones (iOS and otherwise)?

Some of these ideas seem to help a bit, or in certain circumstances, but then fall apart on others. Can't seem to find a pattern...

Although has some interesting possibilities:
http://stackoverflow.com/questions/17798091/osx-inertia-scrolling-causing-mousewheel-js-to-register-multiple-mousewheel-even

Yet also, not quite THE answer.

DigitalWheelie commented Oct 8, 2013

Any recent, all-encompassing solution w/ the latest version, that will work when the Apple Magic Mouse is present, but also if not, on Windows, tablets and phones (iOS and otherwise)?

Some of these ideas seem to help a bit, or in certain circumstances, but then fall apart on others. Can't seem to find a pattern...

Although has some interesting possibilities:
http://stackoverflow.com/questions/17798091/osx-inertia-scrolling-causing-mousewheel-js-to-register-multiple-mousewheel-even

Yet also, not quite THE answer.

@brandonaaron

This comment has been minimized.

Show comment
Hide comment
@brandonaaron

brandonaaron Oct 23, 2013

Contributor

The issue @NeekGerd brought up is actually related to #66.

Contributor

brandonaaron commented Oct 23, 2013

The issue @NeekGerd brought up is actually related to #66.

@ghost ghost assigned brandonaaron Oct 25, 2013

@brandonaaron

This comment has been minimized.

Show comment
Hide comment
@brandonaaron

brandonaaron Nov 14, 2013

Contributor

I added some functionality that can help with this issue in the 3.2.x branch.

$(...).on('mousewheel', { mousewheel: { behavior: 'throttle', delay: 100 } }, function(event) { ... });

or

$(...).on('mousewheel', { mousewheel: { behavior: 'debounce', delay: 100 } }, function(event) { ... });

Contributor

brandonaaron commented Nov 14, 2013

I added some functionality that can help with this issue in the 3.2.x branch.

$(...).on('mousewheel', { mousewheel: { behavior: 'throttle', delay: 100 } }, function(event) { ... });

or

$(...).on('mousewheel', { mousewheel: { behavior: 'debounce', delay: 100 } }, function(event) { ... });

@brandonaaron

This comment has been minimized.

Show comment
Hide comment
@brandonaaron

brandonaaron Nov 15, 2013

Contributor

I went ahead and bumped this to a 4.0.x branch instead of the previously mentioned 3.2.x branch because the level of changes are pretty extreme.

Contributor

brandonaaron commented Nov 15, 2013

I went ahead and bumped this to a 4.0.x branch instead of the previously mentioned 3.2.x branch because the level of changes are pretty extreme.

@brandonaaron

This comment has been minimized.

Show comment
Hide comment
@brandonaaron

brandonaaron Nov 18, 2013

Contributor

In experimenting with this feature I noticed that it might be desirable to prevent the default behavior for all the mouse wheel events that are essentially ignored due to the throttling. In addition I was thinking about utilizing this concept of putting the settings in the data param for a few other nice-to-have features as well... So I think I might change up the setting names a little based on how that work goes.

Also thinking about alternative ways to add this behavior. Possibly just expose a factory-style method that can build the desired delayed handler.

Contributor

brandonaaron commented Nov 18, 2013

In experimenting with this feature I noticed that it might be desirable to prevent the default behavior for all the mouse wheel events that are essentially ignored due to the throttling. In addition I was thinking about utilizing this concept of putting the settings in the data param for a few other nice-to-have features as well... So I think I might change up the setting names a little based on how that work goes.

Also thinking about alternative ways to add this behavior. Possibly just expose a factory-style method that can build the desired delayed handler.

@brandonaaron

This comment has been minimized.

Show comment
Hide comment
@brandonaaron

brandonaaron Nov 20, 2013

Contributor

Another update on this. You can now pass the following as settings for the mousewheel event:

{ mousewheel: { debounce: { delay: 200 } }
{ mousewheel: { throttle: { delay: 200 } }

Or you can roll with the defaults by just setting to true like this:

{ mousewheel: { debounce: true } }
{ mousewheel: { throttle: true } }

Be default it will not prevent the default nor stop the propagation but you can do both like this:

{ mousewheel: { debounce: { preventDefault: true } }
{ mousewheel: { throttle: { preventDefault: true } }

There is another feature that I added as well... intent. It work similar to the popular hoverIntent plugin.

{ mousewheel: { intent: { delay: 300, sensitivity: 7 } }

Or use the defaults and just pass true:

{ mousewheel: { intent: true } }

You can even use both the intent feature and the throttle/debounce but only preventDefault once the user has expressed intent to use the mousewheel on that particular object.

{ mousewheel: { intent: true, throttle: { preventDefault: true } }

I'm still doing lots of testing and exploring of these features/ideas and they very well could change again. All of this work is happening in the 4.0.x branch.

Contributor

brandonaaron commented Nov 20, 2013

Another update on this. You can now pass the following as settings for the mousewheel event:

{ mousewheel: { debounce: { delay: 200 } }
{ mousewheel: { throttle: { delay: 200 } }

Or you can roll with the defaults by just setting to true like this:

{ mousewheel: { debounce: true } }
{ mousewheel: { throttle: true } }

Be default it will not prevent the default nor stop the propagation but you can do both like this:

{ mousewheel: { debounce: { preventDefault: true } }
{ mousewheel: { throttle: { preventDefault: true } }

There is another feature that I added as well... intent. It work similar to the popular hoverIntent plugin.

{ mousewheel: { intent: { delay: 300, sensitivity: 7 } }

Or use the defaults and just pass true:

{ mousewheel: { intent: true } }

You can even use both the intent feature and the throttle/debounce but only preventDefault once the user has expressed intent to use the mousewheel on that particular object.

{ mousewheel: { intent: true, throttle: { preventDefault: true } }

I'm still doing lots of testing and exploring of these features/ideas and they very well could change again. All of this work is happening in the 4.0.x branch.

@brandonaaron

This comment has been minimized.

Show comment
Hide comment
@brandonaaron

brandonaaron Nov 21, 2013

Contributor

I just landed leading, trailing, and maxDelay options for throttle/debounce settings in the 4.0.x branch. The maxDelay setting only applies to debounce. By default leading is false and trailing is true for debounce while both leading and trailing are true for throttle.

Contributor

brandonaaron commented Nov 21, 2013

I just landed leading, trailing, and maxDelay options for throttle/debounce settings in the 4.0.x branch. The maxDelay setting only applies to debounce. By default leading is false and trailing is true for debounce while both leading and trailing are true for throttle.

@mikaa123

This comment has been minimized.

Show comment
Hide comment
@mikaa123

mikaa123 Nov 23, 2013

awesome man. keep up the good work.

mikaa123 commented Nov 23, 2013

awesome man. keep up the good work.

@jashwant

This comment has been minimized.

Show comment
Hide comment
@jashwant

jashwant Dec 7, 2013

Great update on this @brandonaaron . debounce stops the execution for given seconds. But what does the throttle do then ? Can you create a simple demo, where I can see how I can use those and test ?

jashwant commented Dec 7, 2013

Great update on this @brandonaaron . debounce stops the execution for given seconds. But what does the throttle do then ? Can you create a simple demo, where I can see how I can use those and test ?

@miguelpeixe

This comment has been minimized.

Show comment
Hide comment
@miguelpeixe

miguelpeixe Dec 9, 2013

@jashwant throttle caches the event action and do one at a time, by the delay you specified. debounce doesn't cache, executes only 1 and throw away the subsequent actions until the next release (timeout of the delay specified)

miguelpeixe commented Dec 9, 2013

@jashwant throttle caches the event action and do one at a time, by the delay you specified. debounce doesn't cache, executes only 1 and throw away the subsequent actions until the next release (timeout of the delay specified)

@miguelpeixe

This comment has been minimized.

Show comment
Hide comment
@miguelpeixe

miguelpeixe Dec 9, 2013

I'm still having issues controlling macosx mousewheel event. I can't use debounce feature because it waits the specified ms to start, I need it to start immediatelly and only allow to scroll again after some time.

I'm able to do that normally on Windows and Linux (any browser) with my own code. On MacOSX feels erratic, some times it works, but with a "strong" mousewheel, it executes the event again before the time. No idea why, how or how to stop it.

Here's a link

Here's the code:

var enableRun = true;

var runSections = function(delta) {

    if(enableRun) {

        if(delta < 0) {
            // up
            self.sly.prev();
        } else if(delta > 0) {
            // down
            self.sly.next();
        }

        enableRun = false;

        setTimeout(function() {
            enableRun = true;
        }, 800);

    }

};

var homeScroll = function(event) {

    var delta = event.deltaY;

    if(self.sly.initialized) {

        var items = self.sly.items;
        var current = self.sly.rel;
        var isLastItem = (items.length - 1 === current.lastItem);

        if(isLastItem) {

            if(delta < 0) {

                runSections(delta);

                event.stopPropagation();
                event.preventDefault();

            }

            if(!enableRun) {
                event.stopPropagation();
                event.preventDefault();
            }

        } else {

            runSections(delta);

            event.stopPropagation();
            event.preventDefault();

        }

    }

};

$(window).on('mousewheel', homeScroll);

miguelpeixe commented Dec 9, 2013

I'm still having issues controlling macosx mousewheel event. I can't use debounce feature because it waits the specified ms to start, I need it to start immediatelly and only allow to scroll again after some time.

I'm able to do that normally on Windows and Linux (any browser) with my own code. On MacOSX feels erratic, some times it works, but with a "strong" mousewheel, it executes the event again before the time. No idea why, how or how to stop it.

Here's a link

Here's the code:

var enableRun = true;

var runSections = function(delta) {

    if(enableRun) {

        if(delta < 0) {
            // up
            self.sly.prev();
        } else if(delta > 0) {
            // down
            self.sly.next();
        }

        enableRun = false;

        setTimeout(function() {
            enableRun = true;
        }, 800);

    }

};

var homeScroll = function(event) {

    var delta = event.deltaY;

    if(self.sly.initialized) {

        var items = self.sly.items;
        var current = self.sly.rel;
        var isLastItem = (items.length - 1 === current.lastItem);

        if(isLastItem) {

            if(delta < 0) {

                runSections(delta);

                event.stopPropagation();
                event.preventDefault();

            }

            if(!enableRun) {
                event.stopPropagation();
                event.preventDefault();
            }

        } else {

            runSections(delta);

            event.stopPropagation();
            event.preventDefault();

        }

    }

};

$(window).on('mousewheel', homeScroll);
@brandonaaron

This comment has been minimized.

Show comment
Hide comment
@brandonaaron

brandonaaron Dec 9, 2013

Contributor

@miguelpeixe you can turn on a leading debounce behavior. By default leading is false and trailing is true for debounce. There is also a maxDelay option for the debounce behavior.

$(...).on('mousewheel', { mousewheel: { debounce: { leading: true, trailing: false, maxDelay: 500 } }, fn);

Related code for the leading/trailing default settings: https://github.com/brandonaaron/jquery-mousewheel/blob/4.0.x/jquery.mousewheel.js#L206-L207

Contributor

brandonaaron commented Dec 9, 2013

@miguelpeixe you can turn on a leading debounce behavior. By default leading is false and trailing is true for debounce. There is also a maxDelay option for the debounce behavior.

$(...).on('mousewheel', { mousewheel: { debounce: { leading: true, trailing: false, maxDelay: 500 } }, fn);

Related code for the leading/trailing default settings: https://github.com/brandonaaron/jquery-mousewheel/blob/4.0.x/jquery.mousewheel.js#L206-L207

@miguelpeixe

This comment has been minimized.

Show comment
Hide comment
@miguelpeixe

miguelpeixe Dec 9, 2013

Thanks @brandonaaron, what does maxDelay do?

miguelpeixe commented Dec 9, 2013

Thanks @brandonaaron, what does maxDelay do?

@brandonaaron

This comment has been minimized.

Show comment
Hide comment
@brandonaaron

brandonaaron Dec 9, 2013

Contributor

If the event is debounced for maxDelay milliseconds it will force a fire of the event.

Contributor

brandonaaron commented Dec 9, 2013

If the event is debounced for maxDelay milliseconds it will force a fire of the event.

@brandonaaron

This comment has been minimized.

Show comment
Hide comment
@brandonaaron

brandonaaron Dec 17, 2013

Contributor

@miguelpeixe Did the additional settings for debounce work for your particular use-case?

Contributor

brandonaaron commented Dec 17, 2013

@miguelpeixe Did the additional settings for debounce work for your particular use-case?

@miguelpeixe

This comment has been minimized.

Show comment
Hide comment
@miguelpeixe

miguelpeixe Dec 17, 2013

@brandonaaron actually no, my client decided to disable our custom wheel feature but I'm still very interested in solving this out. Such a simple thing, causing so much stress, that's weird.

Do you know what I'm trying to do? if you do and want to solve this, would be nice to have some help!

In my case, I don't really want to force a wheel event, I just need to control it to happen only on the given ms (if the user wants to, with leading turned on). I couldn't manage to do that with the available settings. The closest I got was with the code I previously posted here (worked on every os and browser, except macosx).

miguelpeixe commented Dec 17, 2013

@brandonaaron actually no, my client decided to disable our custom wheel feature but I'm still very interested in solving this out. Such a simple thing, causing so much stress, that's weird.

Do you know what I'm trying to do? if you do and want to solve this, would be nice to have some help!

In my case, I don't really want to force a wheel event, I just need to control it to happen only on the given ms (if the user wants to, with leading turned on). I couldn't manage to do that with the available settings. The closest I got was with the code I previously posted here (worked on every os and browser, except macosx).

@fenicento

This comment has been minimized.

Show comment
Hide comment
@fenicento

fenicento Feb 1, 2014

Hi, I'm having the same issue of miguelpeixe. I can control events on all browsers on windows; on mac Os x I'm using a magic mouse or a trackpad: on firefox everything goes fine, while on chrome (espcially with strong wheel actions) things go out of control and preventDefault seems to be ignored... the code is pretty similar to miguelpeixe's one, I can post it if you think it can be useful...

fenicento commented Feb 1, 2014

Hi, I'm having the same issue of miguelpeixe. I can control events on all browsers on windows; on mac Os x I'm using a magic mouse or a trackpad: on firefox everything goes fine, while on chrome (espcially with strong wheel actions) things go out of control and preventDefault seems to be ignored... the code is pretty similar to miguelpeixe's one, I can post it if you think it can be useful...

@edeesims1

This comment has been minimized.

Show comment
Hide comment
@edeesims1

edeesims1 Feb 12, 2014

I currently have the following

$(document).on('mousewheel', { mousewheel:{ debounce: { leading: true, trailing: false, preventDefault: true } } }, function(e) {

But when I scroll with a trackpad, I am still getting 3 events firing. I am trying to use this to scroll to specific positions on my page. Works great with a mouse but not with a trackpad.

Any suggestions?

edeesims1 commented Feb 12, 2014

I currently have the following

$(document).on('mousewheel', { mousewheel:{ debounce: { leading: true, trailing: false, preventDefault: true } } }, function(e) {

But when I scroll with a trackpad, I am still getting 3 events firing. I am trying to use this to scroll to specific positions on my page. Works great with a mouse but not with a trackpad.

Any suggestions?

@brandonaaron

This comment has been minimized.

Show comment
Hide comment
@brandonaaron

brandonaaron Feb 12, 2014

Contributor

@edeesims1 The default delay is only 100ms. Try tweaking the delay to see if that gets you a better result.

Contributor

brandonaaron commented Feb 12, 2014

@edeesims1 The default delay is only 100ms. Try tweaking the delay to see if that gets you a better result.

@marcbelletre

This comment has been minimized.

Show comment
Hide comment
@marcbelletre

marcbelletre Mar 4, 2014

Hi everyone,

I went here a few times ago to find a solution and I finally found one by myself. I wanted to share it with you so here it is.
Everytime the event is fired, I check if the previous event was fired less than 100ms before and if the event were fired less than 10 times. Else, I don't allow scrolling so the event can be automatically fired only 10 times by the browser. If the difference between the two times is greater than 100ms, we can conclude that the event was fired by the user, so we can allow scrolling.

function mouseHandle(event) {
    newDate = new Date();
    var scrollAllowed = true;

    if( wheel < 10 && (newDate.getTime()-oldDate.getTime()) < 100 ) {
        scrollPos -= event.deltaY*(10-wheel);
        wheel++;
    }
    else {
        if( (newDate.getTime()-oldDate.getTime()) > 100 ) {
            wheel = 0;
            scrollPos -= event.deltaY*60;
        }
        else {
            scrollAllowed = false;
        }
    }

    oldDate = new Date();

    if( scrollAllowed ) {
        // do your stuff here
    }
}

I hope this could help. In my case it seems to work pretty good !

marcbelletre commented Mar 4, 2014

Hi everyone,

I went here a few times ago to find a solution and I finally found one by myself. I wanted to share it with you so here it is.
Everytime the event is fired, I check if the previous event was fired less than 100ms before and if the event were fired less than 10 times. Else, I don't allow scrolling so the event can be automatically fired only 10 times by the browser. If the difference between the two times is greater than 100ms, we can conclude that the event was fired by the user, so we can allow scrolling.

function mouseHandle(event) {
    newDate = new Date();
    var scrollAllowed = true;

    if( wheel < 10 && (newDate.getTime()-oldDate.getTime()) < 100 ) {
        scrollPos -= event.deltaY*(10-wheel);
        wheel++;
    }
    else {
        if( (newDate.getTime()-oldDate.getTime()) > 100 ) {
            wheel = 0;
            scrollPos -= event.deltaY*60;
        }
        else {
            scrollAllowed = false;
        }
    }

    oldDate = new Date();

    if( scrollAllowed ) {
        // do your stuff here
    }
}

I hope this could help. In my case it seems to work pretty good !

@thSoft

This comment has been minimized.

Show comment
Hide comment
@thSoft

thSoft Mar 15, 2014

Wow, @Prettyletter, your workaround works perfectly! Thank you! @brandonaaron, have you considered incorporating it to the code?

thSoft commented Mar 15, 2014

Wow, @Prettyletter, your workaround works perfectly! Thank you! @brandonaaron, have you considered incorporating it to the code?

@jcsuzanne

This comment has been minimized.

Show comment
Hide comment
@jcsuzanne

jcsuzanne Mar 24, 2014

+100!!!! Finally ;)

In the "debounce" function way, i update the script like this

var killbounce = function(_func, _wait)
{
var
wheel = 0
, oldDate = new Date()
, scrollPos = 0
;
return function() {

        var
            context         =   this
        ,   args            =   arguments
        ,   event           =   args[0]
        ,   getDeltaY       =   event.deltaY
        ,   newDate         =   new Date()
        ,   newTime         =   newDate.getTime()
        ,   oldTime         =   oldDate.getTime()
        ,   scrollAllowed   =   true
        ;

        if( wheel < 10 && (newTime-oldTime) < _wait ) {
            scrollPos -= getDeltaY*(10-wheel);
            wheel++;
        }
        else {
            if( (newTime-oldTime) > _wait ) {
                wheel = 0;
                scrollPos -= getDeltaY*60;
            }
            else {
                scrollAllowed = false;
            }
        }
        oldDate = new Date();
        if( scrollAllowed ) {
            _func.apply(context, args);
        }
    }
};

sorry for the trash display...

jcsuzanne commented Mar 24, 2014

+100!!!! Finally ;)

In the "debounce" function way, i update the script like this

var killbounce = function(_func, _wait)
{
var
wheel = 0
, oldDate = new Date()
, scrollPos = 0
;
return function() {

        var
            context         =   this
        ,   args            =   arguments
        ,   event           =   args[0]
        ,   getDeltaY       =   event.deltaY
        ,   newDate         =   new Date()
        ,   newTime         =   newDate.getTime()
        ,   oldTime         =   oldDate.getTime()
        ,   scrollAllowed   =   true
        ;

        if( wheel < 10 && (newTime-oldTime) < _wait ) {
            scrollPos -= getDeltaY*(10-wheel);
            wheel++;
        }
        else {
            if( (newTime-oldTime) > _wait ) {
                wheel = 0;
                scrollPos -= getDeltaY*60;
            }
            else {
                scrollAllowed = false;
            }
        }
        oldDate = new Date();
        if( scrollAllowed ) {
            _func.apply(context, args);
        }
    }
};

sorry for the trash display...

@brandonaaron

This comment has been minimized.

Show comment
Hide comment
@brandonaaron

brandonaaron Mar 24, 2014

Contributor

Sorry I haven't had the time to dig into this some more. Looks promising. Might try to incorporate this into the next major release with the idea of the settings so that it can be configurable. I don't think I'll have time until next month though.

Contributor

brandonaaron commented Mar 24, 2014

Sorry I haven't had the time to dig into this some more. Looks promising. Might try to incorporate this into the next major release with the idea of the settings so that it can be configurable. I don't think I'll have time until next month though.

@gstaruk

This comment has been minimized.

Show comment
Hide comment
@gstaruk

gstaruk May 2, 2014

Hi there, just wondering when the new version of the plugin is due for release?

gstaruk commented May 2, 2014

Hi there, just wondering when the new version of the plugin is due for release?

@majorwaves

This comment has been minimized.

Show comment
Hide comment
@majorwaves

majorwaves May 2, 2014

I think I'm trying to achieve the same things as @Prettyletter and @jcsuzanne, but I'm having trouble putting in their code. Could someone hold my hand and tell me how they implemented that in relation to the '$(document).on('mousewheel'…' line.

majorwaves commented May 2, 2014

I think I'm trying to achieve the same things as @Prettyletter and @jcsuzanne, but I'm having trouble putting in their code. Could someone hold my hand and tell me how they implemented that in relation to the '$(document).on('mousewheel'…' line.

@msimpson

This comment has been minimized.

Show comment
Hide comment
@msimpson

msimpson Dec 19, 2014

The method works by implementing a sliding window. Watch the mouse wheel events and keep a history/sample of the nine most recent deltas. Shifting the window forward after each event. Kind of like riding a wave on a surf board. And on each new event, try to detect a peak (hasPeak) in the sample of deltas. Like: 3, 3, 9, 15, 23, 15, 9, 3, 3.

If that is found, return true from hasPeak. But, delay peak detection for an entire sample width (ignore 9 to 10 future events). That way, as the window slides over the peak it's quieted from registering true multiple times.

The other bit of code in the event handler (second line, below):

if (hasPeak()) hash();
else if ((deltas[8] == null || Math.abs(deltas[8]) == 120) && Math.abs(delta) == 120) hash();

That checks to see if the first delta in history is null or at the standard 120 delta while the current delta is at 120 as well. And If so, it assumes a normal mouse wheel event and fires.

@JakedUp
Here is a demo specifically for implementation:
http://jsfiddle.net/n7bk6pb9/7/

msimpson commented Dec 19, 2014

The method works by implementing a sliding window. Watch the mouse wheel events and keep a history/sample of the nine most recent deltas. Shifting the window forward after each event. Kind of like riding a wave on a surf board. And on each new event, try to detect a peak (hasPeak) in the sample of deltas. Like: 3, 3, 9, 15, 23, 15, 9, 3, 3.

If that is found, return true from hasPeak. But, delay peak detection for an entire sample width (ignore 9 to 10 future events). That way, as the window slides over the peak it's quieted from registering true multiple times.

The other bit of code in the event handler (second line, below):

if (hasPeak()) hash();
else if ((deltas[8] == null || Math.abs(deltas[8]) == 120) && Math.abs(delta) == 120) hash();

That checks to see if the first delta in history is null or at the standard 120 delta while the current delta is at 120 as well. And If so, it assumes a normal mouse wheel event and fires.

@JakedUp
Here is a demo specifically for implementation:
http://jsfiddle.net/n7bk6pb9/7/

@lemonlab

This comment has been minimized.

Show comment
Hide comment
@lemonlab

lemonlab Dec 22, 2014

Thank you @msimpson for this solution & example.
But i don't see how can i "hack" the version 3.1.12 to make this work with your "hasPeak" function.

lemonlab commented Dec 22, 2014

Thank you @msimpson for this solution & example.
But i don't see how can i "hack" the version 3.1.12 to make this work with your "hasPeak" function.

@msimpson

This comment has been minimized.

Show comment
Hide comment
@msimpson

msimpson Dec 23, 2014

@francoismartin
I'm not terribly sure if this should be added into the plugin, itself. The plugin provides compatible mouse wheel events with normalized deltas. Whereas my code profiles this provided data. Nonetheless, I have constructed a hacky edition of the jquery.mousewheel.js found here:

https://gist.github.com/msimpson/44941935eae5505bf1ec

The addition is very passive. It is enabled or disabled via the inertialProfiling setting, and is enable by default. When an inertial chain occurs and a peak is found, a small property is added to the event object called inertialGesture which is set to the current timestamp. That should be sufficient for triggering on inertial gestures and separating them.

This is only an example, of course.

msimpson commented Dec 23, 2014

@francoismartin
I'm not terribly sure if this should be added into the plugin, itself. The plugin provides compatible mouse wheel events with normalized deltas. Whereas my code profiles this provided data. Nonetheless, I have constructed a hacky edition of the jquery.mousewheel.js found here:

https://gist.github.com/msimpson/44941935eae5505bf1ec

The addition is very passive. It is enabled or disabled via the inertialProfiling setting, and is enable by default. When an inertial chain occurs and a peak is found, a small property is added to the event object called inertialGesture which is set to the current timestamp. That should be sufficient for triggering on inertial gestures and separating them.

This is only an example, of course.

@d4nyll

This comment has been minimized.

Show comment
Hide comment
@d4nyll

d4nyll May 6, 2015

I took some inspiration from @msimpson and created lethargy, that helps you detect when an event is fired from inertial scroll. You can then use this information to decide whether to run a function or not.

Lethargy works primarily by picking up when the wheelDelta values are decreasing, as you'll observe towards the end of the inertial scroll.

Please do check it out and give me feedback!

d4nyll commented May 6, 2015

I took some inspiration from @msimpson and created lethargy, that helps you detect when an event is fired from inertial scroll. You can then use this information to decide whether to run a function or not.

Lethargy works primarily by picking up when the wheelDelta values are decreasing, as you'll observe towards the end of the inertial scroll.

Please do check it out and give me feedback!

@f0rmat1k

This comment has been minimized.

Show comment
Hide comment
@f0rmat1k

f0rmat1k May 28, 2015

Guys, we have written the plugin that solves inertial problems. Check it out

f0rmat1k commented May 28, 2015

Guys, we have written the plugin that solves inertial problems. Check it out

@martinbroos

This comment has been minimized.

Show comment
Hide comment
@martinbroos

martinbroos Jul 5, 2015

Any news on this bug? I tried Lethargy but that didn't work for me.
For now i did a simple check on mac users and lowered the delta so it won't be too enoying for users.

        $("html, body").on('mousewheel', function (event, delta) {
            event.preventDefault();
            event.stopPropagation();

            // temp solution lower scroll speed on mac to minimize Inertia Scrolling issue
            var isMac = /mac/i.test(navigator.platform);

            if (isMac) {
                this.scrollLeft -= (delta * 2);
            } else {
                this.scrollLeft -= (delta * 30);
            }
        });

The strange thing is that an older version (3.0.6) of this plugin does work. See https://css-tricks.com/examples/HorzScrolling/

But this version probably has some other cross browser issues so I rather not go back.

martinbroos commented Jul 5, 2015

Any news on this bug? I tried Lethargy but that didn't work for me.
For now i did a simple check on mac users and lowered the delta so it won't be too enoying for users.

        $("html, body").on('mousewheel', function (event, delta) {
            event.preventDefault();
            event.stopPropagation();

            // temp solution lower scroll speed on mac to minimize Inertia Scrolling issue
            var isMac = /mac/i.test(navigator.platform);

            if (isMac) {
                this.scrollLeft -= (delta * 2);
            } else {
                this.scrollLeft -= (delta * 30);
            }
        });

The strange thing is that an older version (3.0.6) of this plugin does work. See https://css-tricks.com/examples/HorzScrolling/

But this version probably has some other cross browser issues so I rather not go back.

@Stiropor

This comment has been minimized.

Show comment
Hide comment
@Stiropor

Stiropor Sep 21, 2015

@f0rmat1k You plugin works excellent! Thanks

Stiropor commented Sep 21, 2015

@f0rmat1k You plugin works excellent! Thanks

@dominicfallows

This comment has been minimized.

Show comment
Hide comment
@dominicfallows

dominicfallows Nov 8, 2015

The plugin (https://github.com/promo/wheel-indicator) from @f0rmat1k works great for my needs also (vertical stacked website, scroll locking to each new section)

dominicfallows commented Nov 8, 2015

The plugin (https://github.com/promo/wheel-indicator) from @f0rmat1k works great for my needs also (vertical stacked website, scroll locking to each new section)

@Yura-ka

This comment has been minimized.

Show comment
Hide comment
@Yura-ka

Yura-ka Feb 9, 2016

My solution to the problem scroll mac osx

$(function() {
    var $domElem = $('#id'); // dom element(or group) which should be filtered event
    var stopScrollfixMac = false;
    var scrollSumPositive = 0;
    var scrollSumNegative = 0;
    $domElem.on("mousewheel", function (event, 
        if (event.originalEvent.wheelDelta < 0) {
            scrollSumPositive = +event.originalEvent.wheelDelta;
        } else {
            scrollSumNegative = +event.originalEvent.wheelDelta;
        }
        if (scrollSumPositive <= -120 || scrollSumNegative >= 120) {
            scrollSumPositive = 0;
            scrollSumNegative = 0;
            stopScrollfixMac = false;
        } else {
            stopScrollfixMac = true;
        }
        if (stopScrollfixMac) {
            event.preventDefault();
            event.stopPropagation();
            return false;
        } 
    });

});

P.S.
in ms windows for one scroll event.originalEvent.wheelDelta = 120/-120

Yura-ka commented Feb 9, 2016

My solution to the problem scroll mac osx

$(function() {
    var $domElem = $('#id'); // dom element(or group) which should be filtered event
    var stopScrollfixMac = false;
    var scrollSumPositive = 0;
    var scrollSumNegative = 0;
    $domElem.on("mousewheel", function (event, 
        if (event.originalEvent.wheelDelta < 0) {
            scrollSumPositive = +event.originalEvent.wheelDelta;
        } else {
            scrollSumNegative = +event.originalEvent.wheelDelta;
        }
        if (scrollSumPositive <= -120 || scrollSumNegative >= 120) {
            scrollSumPositive = 0;
            scrollSumNegative = 0;
            stopScrollfixMac = false;
        } else {
            stopScrollfixMac = true;
        }
        if (stopScrollfixMac) {
            event.preventDefault();
            event.stopPropagation();
            return false;
        } 
    });

});

P.S.
in ms windows for one scroll event.originalEvent.wheelDelta = 120/-120

@colindcampbell

This comment has been minimized.

Show comment
Hide comment
@colindcampbell

colindcampbell Apr 6, 2016

I'm not sure how, but the smart folks at google figured out a way to address this issue. Check out http://www.google.com/inbox/

If you look at the source it appears that they have some fancy math going on. I can't decipher it but someone more experienced might be able to. Here is the minified version of the functions involved:

function qg() { kg.call(this); this.Sa = 400; this.S = 200; this.Ra = 0; this.fe = !0; this.Ea = !1; this.ld = Z.Zh || !1; this.va = this.$a = null ; this.Va = 0; this.oc = Z.viewport.width; this.Od = 0; this.Pd = 200; this.Hb = this.gg = this.Ee = 0; this.di = 40; if (this.ld) { var a = document.createElement("div"); W(a, "graph-swipe"); document.body.appendChild(a); this.$a = document.createElement("canvas"); a.appendChild(this.$a); this.xf = document.createElement("div"); a.appendChild(this.xf); this.$a.width = this.oc; this.$a.height = this.Sa; this.va = this.$a.getContext("2d"); this.va.lineWidth = 4 } } B(qg, kg); g = qg.prototype; g.aa = function() { qg.m.aa.call(this); this.Ee = Z.da.now(); requestAnimationFrame(x(this.eg, this)) } ; g.Rb = function() { qg.m.Rb.call(this); this.g.f(this.A, "wheel", this.Sf); this.g.f(this.A, "mousewheel", this.Sf) } ; g.Sf = function(a) { a = a.oa; var b = 0; a.wheelDelta && (b = a.wheelDelta / 120); a.detail && (b = -a.detail / 3); a.deltaY && (b = -a.deltaY / 10); void 0 !== a.wheelDeltaY && (b = a.wheelDeltaY / 120); rg(this, b); a.stopPropagation && a.stopPropagation(); a.cancelBubble = !0; a.preventDefault && a.preventDefault(); return a.returnValue = !1 } ; function rg(a, b) { var c = .5 * a.Sa + 30 * b , d = !1; c > a.Sa && (d = !0, c = a.Sa); 0 > c && (d = !0, c = 0); d && a.Ea && (a.Hb += 5); var e = Math.abs(b) > (a.fe ? .01 : .25) , f = Math.abs(b) > Math.abs(a.Ra) , d = 0 > b && c < a.S || 0 < b && c > a.S; 1 === Math.abs(b) && (f = .5 >= Math.abs(a.Ra)); if (e = !a.Ea && e && d && f) a.Ra = b, a.Ea = !0, a.Hb = a.di, clearTimeout(a.gg), a.gg = setTimeout(x(function() { this.Ea = !1 }, a), 1E3), 0 > b ? sg(a) : tg(a); d && (a.S = c); a.Ea ? Math.abs(b) > Math.abs(a.Ra) && (a.Ra = b) : a.Ra = b; a.ld && ug(a, c, e) }

colindcampbell commented Apr 6, 2016

I'm not sure how, but the smart folks at google figured out a way to address this issue. Check out http://www.google.com/inbox/

If you look at the source it appears that they have some fancy math going on. I can't decipher it but someone more experienced might be able to. Here is the minified version of the functions involved:

function qg() { kg.call(this); this.Sa = 400; this.S = 200; this.Ra = 0; this.fe = !0; this.Ea = !1; this.ld = Z.Zh || !1; this.va = this.$a = null ; this.Va = 0; this.oc = Z.viewport.width; this.Od = 0; this.Pd = 200; this.Hb = this.gg = this.Ee = 0; this.di = 40; if (this.ld) { var a = document.createElement("div"); W(a, "graph-swipe"); document.body.appendChild(a); this.$a = document.createElement("canvas"); a.appendChild(this.$a); this.xf = document.createElement("div"); a.appendChild(this.xf); this.$a.width = this.oc; this.$a.height = this.Sa; this.va = this.$a.getContext("2d"); this.va.lineWidth = 4 } } B(qg, kg); g = qg.prototype; g.aa = function() { qg.m.aa.call(this); this.Ee = Z.da.now(); requestAnimationFrame(x(this.eg, this)) } ; g.Rb = function() { qg.m.Rb.call(this); this.g.f(this.A, "wheel", this.Sf); this.g.f(this.A, "mousewheel", this.Sf) } ; g.Sf = function(a) { a = a.oa; var b = 0; a.wheelDelta && (b = a.wheelDelta / 120); a.detail && (b = -a.detail / 3); a.deltaY && (b = -a.deltaY / 10); void 0 !== a.wheelDeltaY && (b = a.wheelDeltaY / 120); rg(this, b); a.stopPropagation && a.stopPropagation(); a.cancelBubble = !0; a.preventDefault && a.preventDefault(); return a.returnValue = !1 } ; function rg(a, b) { var c = .5 * a.Sa + 30 * b , d = !1; c > a.Sa && (d = !0, c = a.Sa); 0 > c && (d = !0, c = 0); d && a.Ea && (a.Hb += 5); var e = Math.abs(b) > (a.fe ? .01 : .25) , f = Math.abs(b) > Math.abs(a.Ra) , d = 0 > b && c < a.S || 0 < b && c > a.S; 1 === Math.abs(b) && (f = .5 >= Math.abs(a.Ra)); if (e = !a.Ea && e && d && f) a.Ra = b, a.Ea = !0, a.Hb = a.di, clearTimeout(a.gg), a.gg = setTimeout(x(function() { this.Ea = !1 }, a), 1E3), 0 > b ? sg(a) : tg(a); d && (a.S = c); a.Ea ? Math.abs(b) > Math.abs(a.Ra) && (a.Ra = b) : a.Ra = b; a.ld && ug(a, c, e) }

@bercikboris

This comment has been minimized.

Show comment
Hide comment
@bercikboris

bercikboris May 15, 2016

please is there any WORKING solution for OS X ?

bercikboris commented May 15, 2016

please is there any WORKING solution for OS X ?

@davidroffe

This comment has been minimized.

Show comment
Hide comment
@davidroffe

davidroffe Nov 16, 2016

Just wanted to chime in and add I had a similar problem to @dominicfallows and @f0rmat1k's solution worked great!

davidroffe commented Nov 16, 2016

Just wanted to chime in and add I had a similar problem to @dominicfallows and @f0rmat1k's solution worked great!

@permanyer

This comment has been minimized.

Show comment
Hide comment
@permanyer

permanyer Nov 28, 2016

@f0rmat1k's solution worked great

+1

permanyer commented Nov 28, 2016

@f0rmat1k's solution worked great

+1

@thecheshirecat

This comment has been minimized.

Show comment
Hide comment
@thecheshirecat

thecheshirecat Mar 23, 2017

I'm having troubles with MAC mouses/trackpads too. The thing is that the inertia stills there, and I need to get rid of it if possible.

$("body").on("mousewheel", function(e) {
    var body = $(this);
    //If the body doesn't have the "animating" class, we add it and do the animations here,
    //If it has it, it doesn't does anything until it finishes animating
    if(!body.hasClass("animating")) {
        body.addClass("animating");
        //MY CODE GOES HERE
        ...
        setTimeout(function() {
            body.removeClass("animating");
        }, 1500);
    }
});

That's my code, but the inertia makes the scrolling again after the 1500ms of the first scroll.

Is this issue fixed and I'm missing something?

PS: i used the latest version of the plug-in

thecheshirecat commented Mar 23, 2017

I'm having troubles with MAC mouses/trackpads too. The thing is that the inertia stills there, and I need to get rid of it if possible.

$("body").on("mousewheel", function(e) {
    var body = $(this);
    //If the body doesn't have the "animating" class, we add it and do the animations here,
    //If it has it, it doesn't does anything until it finishes animating
    if(!body.hasClass("animating")) {
        body.addClass("animating");
        //MY CODE GOES HERE
        ...
        setTimeout(function() {
            body.removeClass("animating");
        }, 1500);
    }
});

That's my code, but the inertia makes the scrolling again after the 1500ms of the first scroll.

Is this issue fixed and I'm missing something?

PS: i used the latest version of the plug-in

@anojht

This comment has been minimized.

Show comment
Hide comment
@anojht

anojht Apr 12, 2017

Im not sure if this helps but I had scrolling issues on mac whereby scroll event was being fired more than once and causing pages to scroll more than intended. So eventually we implemented the following it is working on mac without causing issues on other platforms: cubetransition

The code above detects scroll events over duration of time and determines if being fired by a mouse or a track pad then gives you the option to deal with it accordingly. If it is a track pad then it disable extra scroll behavior with a timeout function.

anojht commented Apr 12, 2017

Im not sure if this helps but I had scrolling issues on mac whereby scroll event was being fired more than once and causing pages to scroll more than intended. So eventually we implemented the following it is working on mac without causing issues on other platforms: cubetransition

The code above detects scroll events over duration of time and determines if being fired by a mouse or a track pad then gives you the option to deal with it accordingly. If it is a track pad then it disable extra scroll behavior with a timeout function.

@sebringj

This comment has been minimized.

Show comment
Hide comment
@sebringj

sebringj Nov 11, 2017

The delta starts slower then goes to a peak, then goes slower again. If continual scrolling, will have this bouncy affect in the data as a user flicks their finger having peaks and troughs of delta values. Code has to address this, not looking at it like a single flat line. I'll see if I have the time.

sebringj commented Nov 11, 2017

The delta starts slower then goes to a peak, then goes slower again. If continual scrolling, will have this bouncy affect in the data as a user flicks their finger having peaks and troughs of delta values. Code has to address this, not looking at it like a single flat line. I'll see if I have the time.

@anojht

This comment has been minimized.

Show comment
Hide comment
@anojht

anojht Nov 12, 2017

@sebringj Your observed behavior is correct. Please see if the following fiddles help speed up the solution process:

jsfiddle1
jsfiddle2

anojht commented Nov 12, 2017

@sebringj Your observed behavior is correct. Please see if the following fiddles help speed up the solution process:

jsfiddle1
jsfiddle2

@sebringj

This comment has been minimized.

Show comment
Hide comment
@sebringj

sebringj Nov 12, 2017

@anojht thanks i made something similar with storing an array checking if > 3 size then check if middle is greater than adjacent code is small and discards array when peak detected and fires callback I’ll post when i get back.

sebringj commented Nov 12, 2017

@anojht thanks i made something similar with storing an array checking if > 3 size then check if middle is greater than adjacent code is small and discards array when peak detected and fires callback I’ll post when i get back.

@sebringj

This comment has been minimized.

Show comment
Hide comment
@sebringj

sebringj commented Nov 12, 2017

well you can see source here https://s3.amazonaws.com/jasonsebring.com/mynticoin/index.html see main.js

@anojht

This comment has been minimized.

Show comment
Hide comment
@anojht

anojht Nov 13, 2017

@sebringj Just checked it out, scrolling is broken on Chrome on Windows 10 when using a mouse with a mouse wheel. It does not trigger the page scroll sometimes. Also, that's a beautiful website!

anojht commented Nov 13, 2017

@sebringj Just checked it out, scrolling is broken on Chrome on Windows 10 when using a mouse with a mouse wheel. It does not trigger the page scroll sometimes. Also, that's a beautiful website!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment