Prevent scroll trigger during on scroll animation (jQuery.appear.js)?

672 views Asked by At

Using: jQuery.appear.js and countUp.js plugins

I'm getting an issue when the user is scrolling, the event is continually getting triggered. I've also tried doing it without the jQuery.appear plugin and using on.scroll(function(){}); but I get the same result. Any scroll event before the animation is complete keeps triggering the animation and causing it to malfunction. I tried $(window).unbind('scroll'); which works, but then that breaks any other on-scroll animation.

var $element = $('.element');
$element.appear();
$(document.body).on('appear', '.element', function () {
    var $this = $(this),
        countTo = $this.attr('data-count');

    $({countNum: $this.text()}).animate({
            countNum: countTo
        },
        {
            duration: 1000,
            easing: 'linear',
            step: function () {
                $this.text(Math.floor(this.countNum));
            },
            complete: function () {
                $this.text(this.countNum);
            }
        }
    );
});

How can I prevent scroll events from triggering the animation while the animation is still in progress?

Check out https://jsfiddle.net/efqhgg5L/. When you keep scrolling around the numbers while they're still ticking, the animation won't complete.

1

There are 1 answers

2
vellip On

The problem lies in how often the appear event gets triggered, and it gets constantly triggered as you scroll (I assume that's how jquery.appear.js is coded). Changing the event binding from $(document.body).on('appear', ...) to $(document.body).one('appear',...) (on vs. one) triggers the event only the first time. Since you are using delegated event handling (set the event to document and then check for the event target) it only triggers for the first counter that appears.

Solution 1: You could implement your own logic where you keep track of the counters that already appeared and if the appear event gets triggered on a counter that already appeared you bail before doing the .animate again. This can be done either by storing the state (has it appeared initially) for every counter.

Solution 2: Or, probably the easier way, you add a class once a counter started animating and check for that class with e.g. jQuery's hasClass and return before running .animate again.