我正在继续previous post,但是我想我要打开一个新线程,因为它采用了不同的方法并且具有更多实际代码。无论如何,我试图通过div在窗口中滚动来获得无限循环(另一篇文章中有图片,并且下面的代码有效)。

<html>
    <head>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8">
        <title>Bleh...</title>
        <style type="text/css" media="screen">
            body {
                padding: 0;
                text-align: center;
            }

            #container {
              width: 1000px;
              padding: 10px;
              border: 1px solid #bfbfbf;
              margin: 0 auto;
              position: relative;
            }

            #window {
              width: 400px;
              height: 100px;
              padding: 10px;
              border: 3px solid #666;
              margin: 0 auto;
            }

            .box {
              height: 100px;
              width: 100px;
              border: 1px solid #666666;
              position: absolute;
              z-index: -1;
            }

            .red { background-color: #ff6868;}
            .green { background-color: 7cd980;}
            .blue { background-color: #5793ea;}
            .yellow { background-color: #f9f69e;}
            .purple { background-color: #ffbffc;}
            .cyan { background-color: #bff3ff;}

        </style>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
        <script type="text/javascript" charset="utf-8">
            $(window).load(function() {
               arrangeBoxes();
               setInterval('shiftLeft()', 3000);
            });

            // arrange the boxes to be aligned in a row
            function arrangeBoxes() {
              $('.box').each( function(i, item) {
                var position = $('#window').position().left + 3 + i * ( $(item).width() + 10 );
                $(item).css('left', position+'px')
              });
            }

            // shifts all the boxes to the left, then checks if any left the window
            function shiftLeft() {
              $('.box').animate({'left' : "-=100px"}, 3000, 'linear');
              checkEdge();
            }

            // returns the new location for the box that exited the window
            function getNewPosition() {
              return $('.box:last').position().left + $('.box:last').outerWidth() + 10;
            }

            // if the box is outside the window, move it to the end
            function checkEdge() {
              var windowsLeftEdge = $('#window').position().left;

              $('.box').each( function(i, box) {

                // right edge of the sliding box
                var boxRightEdge = $(box).position().left + $(box).width();

                // position of last box + width + 10px
                var newPosition = getNewPosition();
                if ( $(box).attr('class').indexOf('red') >=0 ) {
                  console.log('box edge: ' + boxRightEdge + ' window edge: ' + windowsLeftEdge + ' new pos: ' +newPosition);
                }

                if ( parseFloat(boxRightEdge) < parseFloat(windowsLeftEdge) ) {
                  $(box).css('left', newPosition);
                  $(box).remove().appendTo('#window');
                  first = $('.box:first').attr('class');
                  console.log('first is ' +  first);
                }
              });


            }
        </script>
    </head>
    <body id="index">
        <div id="container">
          <div id="window">
            <div class="box red"></div>
            <div class="box green"></div>
            <div class="box blue"></div>
            <div class="box yellow"></div>
            <div class="box purple"></div>
            <div class="box cyan"></div>
          </div>
        </div>
    </body>
</html>


无论如何,问题是我可以使这些框向左移动,但是当我运行整个程序时,我无法使前导框弹出到该行的末尾。当我分别运行每个功能(使用Firebug)时-

>> $('.box').animate({'left' : "-=100px"}, 3000, 'linear');
>> checkEdge()


效果很好。当我将它们放在一起时,我只是从右到左连续运动,直到盒子离开屏幕,所以必须是它们如何相互作用。我希望这是有道理的(如果没有,请将上面的代码块另存为html文件并在浏览器中运行)。我已经坚持了一段时间,所以任何帮助都会很棒。谢谢。

最佳答案

您需要像这样设置回调

$('.box').animate({'left' : "-=100px"}, 3000, 'linear', checkEdge());


checkEdge()不是checkEdge

在此处查看有效的解决方案http://jsbin.com/uceqi(只需复制粘贴您的代码)



在这里,如果不放置牙套,实际上会有所不同。带花括号的版本每个动画执行一次checkEdge()(实际上,实际上,它在动画开始之前执行checkEdge。当checkEdge()语句到达之前甚至在$...animte(..)本身执行之前,就会调用animate()函数。 checkEdge将导致函数作为参数传递,通常是正确的方法。

不带括号的版本将对与选择器匹配的元素数量执行一次checkEdge。在这种情况下6次。

因此,从技术上来讲,您的方法是正确的,因为它将为每个动画元素触发一次回调,并在动画之后触发回调。
但是一旦执行checkEdge显然不是作者想要的(检查checkEdge中的div循环)。当您在所有div上循环几次时,还会导致严重的滞后

6div动画-> 6个回调触发的->回调遍历所有div ==> 36个checkEdge()中的匿名函数执行!

因此,实际的问题是回调同时触发了6次。这样我们就有了比赛条件,动画变得混乱了。由于几个checkEdge()调用在重新定位div时同时工作。

但是您仅会注意到这一点,因为animation-speedsetInterval中的间隔(shiftLeft)是相同的。如果它们不同((间隔+〜1000ms)>动画速度),那么它也将正常工作。但是当然,动画不会流畅。因为shitfLeft()在动画停止后会触发1秒。

您可以检查此示例http://jsbin.com/iwapi3,该示例说明了使用不带花括号的版本时发生的情况。等待一段时间,checkEdge()调用的计数器每3秒增加7。您还将注意到,在某些情况下,动画会部分起作用,并且某些div有时会移回到列表的末尾。

一段时间后,单击按钮,观察带有大括号的版本在运行几次后如何将混乱分类(但现在当然已经弄乱了正确的颜色顺序)。每个动画只调用一次checkEdge()。 (点击按钮后不久,您将获得+7的收益,因为某些回调仍在管道中)

10-08 16:25