14

リストをアニメーション化するための小さなスクリプトを作成しています。これが私のhtml構造です:

<ul>
   <li class="slider"> Item-1 </li>
   <li class="slider"> Item-2 </li>
   <li class="slider"> Item-3 </li>
   ...
   <li class="slider"> Item-13 </li>
   <li class="slider"> Item-14 </li>
   <li class="slider"> Item-15 </li>
</ul>

<button> Next </button>

一度に4つのliのみを表示しています。「次へ」ボタンは、表示された4つのliをフェードアウトします。次の4つのliをフェードインします。しかし、フェードは両方を一緒に適用しています。最初のフェードでコールバック関数を使用しようとしましたが、機能させることができません。

スクリプトは次のとおりです。

$('li:gt(3)').css('display', 'none');

//Define the interval of li to display
var start = 0;
var end = 4;

//Get the ul length
var listlength = $("li").length;

$("button").click(function() { 

  // FadeOut the four displayed li 
  $('ul li').slice(start,end).fadeOut(500, function(){

        // Define the next interval of four li to show
        start = start+4;
        end = end+4;

        // Test to detect the end of list and reset next interval
        if( start > listlength ){
          start = 0;
          end = 4;
        }

        //Display the new interval
        $('ul li').slice(start,end).fadeIn(500);
  });    
});

手がかりはありますか?

4

2 に答える 2

27

問題は、.fadeOut() コールバックが、最後に 1 回ではなく、アニメーション化された要素ごとに 1 回呼び出されることです。呼び出された回数のカウンターを保持するようにコードを変更することもできますが、はるかに簡単です (少なくとも jQuery 1.6 を想定) .promise() を使用すると、関連するすべてのアニメーションが完了した後に解決されます。

$(document).ready(function () {
    var $lis = $("li.slider"),
        start = 0;

    $lis.hide()
        .slice(start, start + 4)
        .show();

    $("button").click(function () {
        $lis.slice(start, start + 4)
            .fadeOut(500)
            .promise()
            .done(function () {
                start += 4;
                if (start > $lis.length) {
                    start = 0;
                }
                $lis.slice(start, start + 4).fadeIn();
            });
    });
});

デモ: http://jsfiddle.net/w7Yuk

私はあなたのコードにいくつかの変更を加えました。たとえば、li 要素を含む jQuery オブジェクトをキャッシュし、「end」変数を削除しました。

于 2012-04-17T01:32:30.197 に答える
5

私はあなたが持っていたものを変更し、スムーズな移行を実現する素敵な小さなjsFiddle デモを作成しました:

HTML:

ページに他のボタンがある場合に備えて、ボタンに「次へ」の ID を付けて、具体的にターゲットにできるようにします。

<ul>
   <li class="slider"> Item-1 </li>
   <li class="slider"> Item-2 </li>
   <li class="slider"> Item-3 </li>
   <li class="slider"> Item-4 </li>
   <li class="slider"> Item-5 </li>
   <li class="slider"> Item-6 </li>
   <li class="slider"> Item-7 </li>
   <li class="slider"> Item-8 </li>
   <li class="slider"> Item-9 </li>
   <li class="slider"> Item-10 </li>
   <li class="slider"> Item-11 </li>
   <li class="slider"> Item-12 </li>
   <li class="slider"> Item-13 </li>
   <li class="slider"> Item-14 </li>
   <li class="slider"> Item-15 </li>
   <li class="slider"> Item-16 </li>
</ul>

<button id="next"> Next </button>

CSS:

ロード時にうまくフェードインできるように、どちらも表示なしで開始します。

.slider { display: none; }
#next { display: none; }

jQuery:

私は要素をキャッシュするのが好きなので、キャッシュすることから始めました。次に、最初の 4 つの LI 要素と次のボタンの両方をフェードインします。の推奨ハンドラーを使用して.on()、次のボタンのクリック イベントをバインドします。設定後、次のボタンstartと現在の 4 つの LI 要素endを呼び出します。.fadeOut()さて、コールバックが厄介な理由は、それらがセレクターのすべての要素のコールバックであるという事実によるものです (つまり 4 回)。代わりに、.promise()それらすべてが全体として完了するのを待つために使用する必要があり、その後.fadeIn()、次のボタンと次の 4 つの LI 要素の両方でメソッドを呼び出すことができます。.stop(true,true)余談ですが、アニメーションのキューイングを排除するために使用します。

var $list = $("ul li");
var $next = $("#next");
var start = 0;
var end = 4;

$next.fadeIn(500);
$list.slice(start,end).fadeIn(500);

$next.on("click", function() {

  start += 4;
  end += 4;

  if( start >= $list.length ){
    start = 0;
    end = 4;
  }

  $next.stop(true,true).fadeOut(500);
  $list.stop(true,true).fadeOut(500);

  $list.promise().done(function() {
    $list.slice(start,end).stop(true,true).fadeIn(500);
    $next.stop(true,true).fadeIn(500);
  });

});
于 2012-04-17T01:18:19.467 に答える