最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to check each new scroll and avoid Apple mouses issue (multiple-scroll effect) - Stack Overflow

programmeradmin5浏览0评论

I try to make a mousewheel event script, but getting some issues since I'm using an Apple Magic Mouse and its continue-on-scroll function.

I want to do this / (from jQuery Tools Scrollable with Mousewheel - scroll ONE position and stop, using ), but I want a short animation (like 250ms) when scrolling to boxes, AND ability to go throught multiple boxes when scrolling multiple times during one animation. (If I scroll, animation start scrolling to second box, but if I scroll again, I want to go to the third one, and if I scroll two times, to the forth, etc.)

I first thought stopPropagation / preventDefault / return false; could "stop" the mousewheel velocity (and the var delta) – so I can count the number of new scroll events (maybe with a timer) –, but none of them does.

Ideas?

EDIT : If you try to scroll in Google Calendars with these mouses, several calendars are switched, not only one. It seems they can't fix that neither.

EDIT 2 : I thought unbind mousewheel and bind it again after could stop the mousewheel listener (and don't listen to the end of inertia). It did not.

EDIT 3 : tried to work out with Dates (thanks to this post), not optimal but better than nothing /

I try to make a mousewheel event script, but getting some issues since I'm using an Apple Magic Mouse and its continue-on-scroll function.

I want to do this http://jsfiddle/Sg8JQ/ (from jQuery Tools Scrollable with Mousewheel - scroll ONE position and stop, using http://brandonaaron/code/mousewheel/demos), but I want a short animation (like 250ms) when scrolling to boxes, AND ability to go throught multiple boxes when scrolling multiple times during one animation. (If I scroll, animation start scrolling to second box, but if I scroll again, I want to go to the third one, and if I scroll two times, to the forth, etc.)

I first thought stopPropagation / preventDefault / return false; could "stop" the mousewheel velocity (and the var delta) – so I can count the number of new scroll events (maybe with a timer) –, but none of them does.

Ideas?

EDIT : If you try to scroll in Google Calendars with these mouses, several calendars are switched, not only one. It seems they can't fix that neither.

EDIT 2 : I thought unbind mousewheel and bind it again after could stop the mousewheel listener (and don't listen to the end of inertia). It did not.

EDIT 3 : tried to work out with Dates (thanks to this post), not optimal but better than nothing http://jsfiddle/eZ6KE/

Share Improve this question edited May 23, 2017 at 12:09 CommunityBot 11 silver badge asked Oct 4, 2012 at 12:23 JoanJoan 7392 gold badges8 silver badges22 bronze badges 3
  • 1 This won't be an issue just on Magic Mice, but all systems with inertia scrolling (i.e. all recent Macs, many newer PCs), Your suggestion about counting scroll events sounds sensible, and you may have to implement it yourself. – Rich Bradshaw Commented Oct 5, 2012 at 12:59
  • Yes you're right, that's an inertia issue (and I'm experimenting this with my Magic Mouse). If counting scroll events sounds a good fix, I've no idea how to perform this. I tried to check – at each scroll event (called everytime during inertia) if previous delta was > or <, but the curve is not linear, it's elastic on my test. Any ideas ? (Thanks anyway!) – Joan Commented Oct 8, 2012 at 9:12
  • Possible fix : github./brandonaaron/jquery-mousewheel/issues/36 (untested yet). – Joan Commented Jan 28, 2013 at 10:38
Add a ment  | 

3 Answers 3

Reset to default 1

Best way is to use a timeout and check inside the listener if the timeout is still active:

var timeout = null;
var speed = 100; //ms
var canScroll = true;

$(element).on('DOMMouseScroll mousewheel wheel', function(event) {
    // Timeout active? do nothing
    if (timeout !== null) {
        event.preventDefault();
        return false;
    }

    // Get scroll delta, check for the different kind of event indexes regarding delta/scrolls
    var delta = event.originalEvent.detail ? event.originalEvent.detail * (-120) : (
            event.originalEvent.wheelDelta ? event.originalEvent.wheelDelta : (
                    event.originalEvent.deltaY ? (event.originalEvent.deltaY * 1) * (-120) : 0
    ));

    // Get direction
    var scrollDown = delta < 0;

    // This is where you do something with scrolling and reset the timeout
    // If the container can be scrolling, be sure to prevent the default mouse action
    // otherwise the parent container can scroll too
    if (canScroll) {
        timeout = setTimeout(function(){timeout = null;}, speed);
        event.preventDefault();
        return false;
    }

    // Container couldn't scroll, so let the parent scroll
    return true;
});

You can apply this to any scrollable element and in my case, I used the jQuery tools scrollable library but ended up heavily customizing it to improve browser support as well as adding in custom functionality specific to my use case.

One thing you want to be careful of is ensuring that the timeout is sufficiently long enough to prevent multiple events from triggering seamlessly. My solution is effective only if you want to control the scrolling speed of elements and how many should be scrolled at once. If you add console.log(event) to the top of the listener function and scroll using a continuous scrolling peripheral, you will see many mousewheel events being triggered.

Annoyingly the Firefox scroll DOMMouseScroll does not trigger on magic mouse or continuous scroll devices, but for normal scroll devices that have a scroll and stop through the clicking cycle of the mouse wheel.

I had a similar problem on my website and after many failed attempts, I wrote a function, which calculated total offset of selected box and started the animation over. It looked like this:

function getOffset() {
    var offset = 0;
    $("#bio-content").children(".active").prevAll().each(function (i) {
        offset += $(this)[0].scrollHeight;
    });
    offset += $("#bio-content").children(".active")[0].scrollHeight;

    return offset;
}

var offset = getOffset();
$('#bio-content').stop().animate( {
            scrollTop: offset
}, animationTime);

I hope it gives you an idea of how to achieve what you want.

you can try detecting when wheel stops moving, but it would add a delay to your response time

$(document).mousewheel(function() {
  clearTimeout($.data(this, 'timer'));
  $.data(this, 'timer', setTimeout(function() {
     alert("Haven't scrolled in 250ms!");
     //do something
  }, 250));
});

source: jquery mousewheel: detecting when the wheel stops?

or implement flags avoiding the start of a new animation

var isAnimating=false;

$(document).bind("mousewheel DOMMouseScroll MozMousePixelScroll", function(event, delta) {
   event.preventDefault();
   if (isAnimating) return;
   navigateTo(destination);
});

function navigateTo(destination){
   isAnimating = true;
   $('html,body').stop().animate({scrollTop: destination},{plete:function(){isAnimating=false;}});
}
发布评论

评论列表(0)

  1. 暂无评论