Pergunta

I'm using the following code below, to scroll two divs in different directions () but I'm curious to know if you can limit the scroll so it only fires once per scroll (rather than it continually scrolling and sending my functions into an endless loop.

$('.page-left, .page-right').bind('mousewheel', function(event, delta) {
    var windowHeight = $(window).height();
    if (delta < 0) {
        prevProject();
    }
    if (delta > 0) {
        nextProject();
    }
});

You can see where I'm up up to here: http://dev.rdck.co/lyonandlyon/

Thanks in advance, R

Animation functions for reference:

var prevProject = function() { // up arrow/scroll up
    var windowHeight = $(window).height();

    $('.page-left .page-left-wrapper').css({bottom:'auto'});
    $('.page-left .page-left-wrapper').animate({top:0},800, function() {
        $('.page-left .page-left-wrapper').prepend($('.page-left .project-left:last-of-type'));
        $('.page-left .page-left-wrapper').css({top:-windowHeight});
    });
    $('.page-right .page-right-wrapper').css({top:'auto'});
    $('.page-right .page-right-wrapper').animate({bottom:+windowHeight*2},800, function() {
        $('.page-right .page-right-wrapper').append($('.page-right .project-right:first-of-type'));
        $('.page-right .page-right-wrapper').css({bottom:+windowHeight});
    });
};


var nextProject = function() { // down arrow/scroll down
    var windowHeight = $(window).height();

    $('.page-left .page-left-wrapper').animate({top:0},800, function() {
        $('.page-left .page-left-wrapper').prepend($('.page-left .project-left:last-of-type'));
        $('.page-left .page-left-wrapper').css({top:-windowHeight});
    });
    $('.page-right .page-right-wrapper').animate({bottom:+windowHeight*2},800, function() {
        $('.page-right .page-right-wrapper').append($('.page-right .project-right:first-of-type'));
        $('.page-right .page-right-wrapper').css({bottom:+windowHeight});
    });
};
Foi útil?

Solução

You can just check for animation within the mousewheel function (demo)

$('.page-left, .page-right').on('mousewheel', function(event, delta) {
    if ($('.page-left-wrapper, .page-right-wrapper').is(':animated') ) {
        return false;
    }
    var windowHeight = $(window).height();
    if (delta < 0) {
        prevProject();
    }
    if (delta > 0) {
        nextProject();
    }
});

Update: we resolved to use debounce as the long scroll (sliding a finger down a touchpad) needed to be stopped (updated demo).

$(document).keydown( $.debounce( 250, function(e) {
    switch (e.which) {
    case 38: // up arrow
        prevProject();
        break;
    case 40: // down arrow
        nextProject();
        break;
    }
}) );

$('.page-left, .page-right').on('mousewheel', $.debounce( 250, function(event, delta) {
    var windowHeight = $(window).height();
    if (delta < 0) {
        prevProject();
    }
    if (delta > 0) {
        nextProject();
    }
}) );

Outras dicas

You can get around this problem with a flag. You can use a global flag isAnimating and set it to true, if you are currently animating the position of the divs of your website.

So the code can look something like this:

var isAnimating = false;

$('.page-left, .page-right').bind('mousewheel', function(event, delta) {
    // if the div will be animated at this moment return
    if(isAnimating) {
        return;
    }

    var windowHeight = $(window).height();
    if (delta < 0) {
        prevProject();
    }
    if (delta > 0) {
        nextProject();
    }
});

var prevProject = function() {
    isAnimating = true;

    var oneIsDone = false,
        finish = function() {
            // if both animations are done, set the flag to false
            if(oneIsDone) {
                isAnimating = false;
            }
            // at least one is done...
            oneIsDone = true;
        };

    // animate the previous project and set the flag to false (in the callback)
    $('.page-left .page-left-wrapper').css({bottom:'auto'});
    $('.page-left .page-left-wrapper').animate({top:0},800, function() {
        $('.page-left .page-left-wrapper').prepend($('.page-left .project-left:last-of-type'));
        $('.page-left .page-left-wrapper').css({top:-windowHeight});
        finish();
    });
    $('.page-right .page-right-wrapper').css({top:'auto'});
    $('.page-right .page-right-wrapper').animate({bottom:+windowHeight*2},800, function() {
        $('.page-right .page-right-wrapper').append($('.page-right .project-right:first-of-type'));
        $('.page-right .page-right-wrapper').css({bottom:+windowHeight});
        finish(); 
    });
};

var nextProject = function() {
    // the same as in the prevProject function, but only in the other direction
};

I suggest to detect extremums to fire the function:

var mw1 = 0;
var mw2 = 0;
var lock;
$(document).bind('mousewheel', function(evt) {
    var delta = evt.originalEvent.deltaY
    if(((delta > 0 && delta < mw2 && mw2 > mw1) || (delta < 0 && delta > mw2 && mw2 < mw1)) && !lock){
        console.log(mw1 + " " + mw2 + " " + delta)
        // call some function here
        lock = true;
        window.setTimeout(function(){
            lock = false;
        },200)
    }
    mw1 = mw2;
    mw2 = delta;
})

lock is actually should not be necessary but extremums sometimes are found more than once per scroll for some reason.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top