简体   繁体   中英

JavaScript scroll() event endless loop when page scrolled to the bottom

I made a page where every div is animated as soon as the window reaches it when user scrolls the page. I used jQuery to handle the scroll() event.

My animation changes the width of the divs . The problem is when I reach the end of the page, strange things are happening: The scroll() event is triggered by itself in an endless loop, scrolling the page a little bit upwards each time. How to fix it?

<html>
<head>
    <meta charset="UTF-8">
    <script src="jquery-3.3.1.min.js"></script>
</head>
<body>

<div class='fadein' data-fadewidth='1em' id='1'>
Div 1
Long text so that the animation can be seen
</div>

<div class='fadein' data-fadewidth='2em' id='2'>
Div 2
Long text so that the animation can be seen
</div>

<div class='fadein' data-fadewidth='3em' id='3'>
Div 3
Long text so that the animation can be seen
</div>

<div class='fadein' data-fadewidth='4em' id='4'>
Div 4
Long text so that the animation can be seen
</div>

<div class='fadein' data-fadewidth='5em' id='5'>
Div 5
Long text so that the animation can be seen
</div>

<br/>

<style>
div {
    margin-bottom: 30%;
}
</style>

<script>

$(document).ready(function() {

    var refresh = function(cls) {

        $(cls).each( function(el) {
            var bottom_of_object = $(this).offset().top + $(this).outerHeight();
            var bottom_of_window = $(window).scrollTop() + $(window).height();

            var delay = 0;
            var time = 2000;

            var animation = {};

            if ($(this).data('fadewidth') != undefined) {
                animation.width = $(this).data('fadewidth');
            }

            if( bottom_of_window > bottom_of_object - ($(window).height()*0.25) ) {

                setTimeout(function () {
                    $(this).animate(animation, time);
                }.bind(this), delay);

            }
        });
    };

    $(window).scroll(function() {
        console.log(Date(), ' page scrolled ');
        refresh('.fadein')});

    refresh('.fadein');

});

</script>

</body>
</html>

Described behavior was tested in: Firefox 69.0.3 and Chromium 77.0.3865.120 on GNU/Linux 4.19.69-1-MANJARO

I changed your code a little bit. this is the content of your script tag:

<script>

$(document).ready(function() {

    var scrollHandler = function () {
        console.log(Date(), ' page scrolled ');
        refresh('.fadein');
    };

    function refresh(cls) {

        if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
            // you're at the bottom of the page, so remove the event handler.
            $(window).off("scroll", scrollHandler);
        }
        $(cls).each( function(el) {
            var bottom_of_object = $(this).offset().top + $(this).outerHeight();
            var bottom_of_window = $(window).scrollTop() + $(window).height();

            var delay = 0;
            var time = 2000;

            var animation = {};

            if ($(this).data('fadewidth') != undefined) {
                animation.width = $(this).data('fadewidth');
            }

            if( bottom_of_window > bottom_of_object - ($(window).height()*0.25) ) {

                setTimeout(function () {
                    $(this).animate(animation, time);
                }.bind(this), delay);

            }
        });
    };



    $(window).scroll(scrollHandler);


    refresh('.fadein');

});

</script>

I remove the event handler when the user scroll hits the bottom of the page.

But your code still have some problems:

if( bottom_of_window > bottom_of_object - ($(window).height()*0.25) ) {

    setTimeout(function () {
        $(this).animate(animation, time);
    }.bind(this), delay);

}

Here you set this animation too many times that even when user hits the bottom and remove the event handler, still remains animations to be executed.

It happens because you already set them before. So, if you wait some time, when all was executed, the page will stop scrolling up.

Pay attention on that and change how to set the animation in a way that it execute only for one div at the time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM