jquery / jquery-mousewheel

A jQuery plugin that adds cross-browser mouse wheel support.
Other
3.9k stars 1.69k forks source link

osx inertia #36

Closed annam closed 5 years ago

annam commented 12 years ago

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?

d4nyll commented 9 years ago

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 commented 9 years ago

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

martinbroos commented 9 years ago

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 commented 9 years ago

@f0rmat1k You plugin works excellent! Thanks

dominicfallows commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

please is there any WORKING solution for OS X ?

davidroffe commented 7 years ago

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

permanyer commented 7 years ago

@f0rmat1k's solution worked great

+1

thecheshirecat commented 7 years ago

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 commented 7 years ago

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 commented 6 years ago

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 commented 6 years ago

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

jsfiddle1 jsfiddle2

sebringj commented 6 years ago

@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 6 years ago

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

anojht commented 6 years ago

@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!

dmcshehan commented 5 years ago

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);

This worked for me.

szfdiwang commented 4 years ago

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

3Q for the plugin ! nice tools !