3

以前の投稿を続けていますが、別のアプローチを取り、より実際のコードがあるため、新しいスレッドを開くと思いました。とにかく、私は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ファイルとして保存し、ブラウザーで実行します)。私はしばらくこれに固執しているので、どんな助けも素晴らしいでしょう。ありがとう。

4

2 に答える 2

4

このようにコールバックを設定する必要があります

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

checkEdge()いいえcheckEdge

実用的な解決策については、こちらを確認してくださいhttp://jsbin.com/uceqi(コードをコピーして貼り付けるだけです)


ここでは、中かっこを省略した場合に実際に違いが生じます。中かっこ付きのバージョンは、checkEdge()アニメーションごとに1回実行されます(実際にはcheckEdge 、アニメーションが開始する前に実行されます。関数は、それ自体が実行される前であってもステートメントに到達checkEdge()すると呼び出されます。関数は、通常は正しい方法でパラメーターとして渡されます。トーゴ)。$...animte(..)animate()checkEdge

中括弧のないバージョンcheckEdgeは、セレクターと一致する要素の数に対して1回実行されます。この場合は6回です。

したがって、技術的に言えば、アニメーション要素ごとに1回、アニメーションの後にコールバックを起動するため、アプローチは正しいでしょう。しかしcheckEdge、これを一度実行することは、明らかに作者が意図したものではありません(のdivのループを確認してくださいcheckEdge)。また、すべてのdivを数回ループすると、深刻な遅延が発生します

6divsアニメーションの->6xコールバックは、すべてのdivで->コールバックループを起動しました。==>checkEdge()

したがって、実際の問題は、コールバックが6回同時に発生することです。したがって、競合状態が発生し、アニメーションが台無しになります。複数のcheckEdge()呼び出しが同時にdivの再配置に機能するため。

ただし、 (shiftLeft)のとanimation-speed間隔が同じであるため、これに気付くだけです。setIntervalそれらが異なる場合((間隔+〜1000ms)>アニメーション速度)、それも正しく機能します。しかしもちろん、アニメーションは流動的ではありません。shitfLeft()アニメーションが停止した後に1秒を発射するように。

このサンプルhttp://jsbin.com/iwapi3を確認できます。これは、中括弧なしのバージョンを使用した場合に何が起こるかを示しています。しばらく待つと、checkEdge()呼び出しのカウンターが3秒ごとに7ずつ増加します。また、アニメーションが部分的に機能し、一部のdivがリストの最後に戻される場合もあります(場合によっては)。

しばらくしてからボタンをクリックして、中かっこ付きのバージョンが数回の実行後に混乱をどのように分類するかを確認してください(ただし、今ではもちろん、色の正しい順序が混乱しています)。checkEdge()そして、アニメーションごとに1回だけ呼び出します。(ボタンを押した直後に、いくつかのコールバックがまだパイプ内にあるため、さらに+7が得られます)

于 2009-11-18T10:09:11.143 に答える
0

JavaScript の実行は、アニメーション関数の 3000 ミリ秒が消費されるまで待機しません。animate 関数を開始しますが、(0 ~ 1 ミリ秒後に) checkEdge() 関数に移動します。必要な場合がある checkEdge() で状態をチェックしません。

これを防ぐには、checkEdge() 関数を animate 関数へのコールバックとして追加する必要があります。これにより、3000 ミリ秒後に正確に実行されます。

これを試して:

$('.box').animate({'left' : "-=100px"}, 3000, 'linear', checkEdge);
于 2009-11-18T08:41:05.713 に答える