jQuery 清除超时问题

jQuery clearTimeout problems

我想延迟一小会儿一个一个地显示一些元素。为此,我检查 div 是否在视口中。如果是,将显示元素。如果用户向下滚动使得 div 不再出现在视口中,则应清除 setTimeout。但它似乎不起作用!您可以对其进行测试...向下滚动几次然后向上滚动并查看问题。超时未清除,元素显示混乱。

那么我的错误在哪里呢?

<html>
<head>
<title>test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<style type="text/css">
    .div1, .div2, .div3 {
        opacity:0;
        float:left;
        width:300px;
        height:300px;
        font-size:80px;
        margin:20px;
    }
    .show {
        opacity:1;
    }
</style>
</head>
<body>
    <script>
        jQuery(document).ready(function(){
            recheck();
            jQuery(window).scroll(function(){
                recheck();
            });

            var timer1, timer2, timer3;
        });
        function recheck() {
            if (jQuery('.box').is_on_screen()) {
                timer1 = setTimeout(function(){ if (jQuery('.box').is_on_screen()) { jQuery('.box .div1').addClass('show'); } },1000);
                timer2 = setTimeout(function(){ if (jQuery('.box').is_on_screen()) { jQuery('.box .div2').addClass('show'); } },3000);
                timer3 = setTimeout(function(){ if (jQuery('.box').is_on_screen()) { jQuery('.box .div3').addClass('show'); } },5000);
            } else {
                window.clearTimeout(timer1);
                window.clearTimeout(timer2);
                window.clearTimeout(timer3);        
                setTimeout(function(){ jQuery('.box div').removeClass('show'); },1);
            }
        }

        jQuery.fn.is_on_screen = function(){
            var win = jQuery(window);
            var viewport = {
                top : win.scrollTop(),
                left : win.scrollLeft()
            };
            viewport.right = viewport.left + win.width();
            viewport.bottom = viewport.top + win.height();

            var bounds = this.offset();
            bounds.right = bounds.left + this.outerWidth();
            bounds.bottom = bounds.top + this.outerHeight();

            return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
        };
    </script>

    <div style="float:left;width:100%;height:3000px;">

        <div class="box" style="float:left;border:3px solid red;">
            <div class="div1" style="border:3px solid blue;background:#c4caf3;">1</div>
            <div class="div2" style="border:3px solid orange;background:#fbe7cb;">2</div>
            <div class="div3" style="border:3px solid green;background:#d6f1d4;">3</div>
        </div>

    </div>

</body>
</html>

滚动事件会在用户滚动时触发很多次,并且每次您设置另一个超时时,都会覆盖旧超时的 ID。您需要确保只设置一次定时器。

var timer1, timer2, timer3, setTimers = false; // Move these outside the ready function
function recheck() {
  if (jQuery('.box').is_on_screen()) {
    if(!setTimers) { // Only set the timers once
      setTimers = true;
      timer1 = setTimeout(function(){ if (jQuery('.box').is_on_screen()) { jQuery('.box .div1').addClass('show'); } },1000);
      timer2 = setTimeout(function(){ if (jQuery('.box').is_on_screen()) { jQuery('.box .div2').addClass('show'); } },3000);
      timer3 = setTimeout(function(){ if (jQuery('.box').is_on_screen()) { jQuery('.box .div3').addClass('show'); } },5000);
    }
  } else {
    window.clearTimeout(timer1);
    window.clearTimeout(timer2);
    window.clearTimeout(timer3);
    setTimeout(function(){ jQuery('.box div').removeClass('show'); },1);
    setTimers = false; // Allow setting timers again
  }
}