1

ゲーム一覧のページを作っています。ジャンル別にゲームをフィルタリングするラジオ ボタンを追加しました。jQuery を使用して、ユーザーがジャンル フィルターをクリックすると、ゲームのリストをエレガントにフェードインおよびフェードアウトします。

問題は、ラジオ ボタンをクリックするたびに、ゲーム リストがぎこちなくフェードインとフェードアウトを 2 回繰り返すことです。参照: http://jsfiddle.net/animeguy99/pZKda/1/

私が使用しているスクリプトは次のとおりです。

$('input[name$="group1"]').click(function(){
    var radio_value = $(this).val();    
    if(radio_value=='Adventure') {
      $('#games div').fadeOut('slow', function(){
            $('#games .adv').fadeIn();
      });
    }
    else if(radio_value=='Puzzle') {
      $('#games div').fadeOut('slow', function(){
            $('#games .puz').fadeIn();
      });
    }
    else if(radio_value=='Shooter') {
      $('#games div').fadeOut('slow', function(){
            $('#games .sho').fadeIn();
      });
    }
    else if(radio_value=='All') {
      $('#games div').fadeOut('slow', function(){
            $('#games div').fadeIn();
      });
    }
});

DIV クラスで宣言されたジャンル タイプがあります。そのため、ユーザーがラジオをクリックするたびに、すべての DIV (ゲーム) をフェードアウトしてから、DIV クラスごとに要求されたジャンルをフェードインします。

私がグーグルで調べたとき、同様のケースで、これは親子の問題である可能性があることが示唆されました。しかし、それを自分のスクリプトに関連付ける方法については困惑しています。

私は何を見落としていますか?

4

5 に答える 5

1

複数の要素がフェードされている場合のコールバック関数は、期待どおりに機能し.fadeOut()ませ.fadeIn()ん。コールバックは1回だけでなく、すべての要素に対して呼び出されます。

console.log()コールバックの1つに呼び出しを入れる.fadeOut()と、それが複数回ログに記録されることがわかります。(Chrome開発ツールは、これを左側に番号が付いた単一のログエントリにまとめます。)

http://jqapi.com/#p=fadeOut

コールバック関数

指定した場合、アニメーションが完了するとコールバックが発生します。これは、さまざまなアニメーションを順番につなぎ合わせるのに役立ちます。コールバックには引数は送信されませんが、これはアニメーション化されるDOM要素に設定されます。複数の要素がアニメーション化されている場合、コールバックは、アニメーション全体に対して1回ではなく、一致した要素ごとに1回実行されることに注意することが重要です。

jQuery 1.6以降、.promise()メソッドをdeferred.done()メソッドと組み合わせて使用​​すると、一致するすべての要素がアニメーションを完了したときに、アニメーション全体に対して単一のコールバックを実行できます(.promiseの例を参照してください)。 ())。

.promise()重複するコールバックを削除するために使用するコードのバージョンは次のとおりです。また、フェードアウトする要素をfadeOutから除外するというj08691の提案も組み込まれています。

var groups = {
    Adventure: '.adv',
    Puzzle: '.puz',
    Shooter: '.sho',
    All: 'div'
};

function fade( group ) {
    $('#games div')
        .not(group)
        .fadeOut()
        .promise()
        .done( function() {
            console.log( group );
            $('#games ' + group).fadeIn();
        });
}

$('input[name$="group1"]').click(function () {
    fade( groups[ $(this).val() ] );
});

このコードは、重複したコードを1つの関数に結合することにより、元のコードよりも大幅に簡略化されています。最後に、console.log()を残して、行われている呼び出しを確認しました。

また、HTMLに関するいくつかのコメント:<br />XHTMLを作成している場合を除いて、使用する必要はありません。XHTMLを作成していないことを願っています。<br>結構です。さらに重要なことに、<label>ラベル全体がクリック可能になるように、ラジオボタンのラベルにタグを使用する必要があります。

<label><input type="radio" name="group1" value="All" checked>Show All</label><br>
<label><input type="radio" name="group1" value="Adventure">Adventure</label><br>
<label><input type="radio" name="group1" value="Puzzle">Puzzle</label><br>
<label><input type="radio" name="group1" value="Shooter">Shooter</label>

これが更新されたjsfiddleです。

ここでも単純化するための追加の機会があります。valueラジオボタンの属性が特定の文字列「All」、「Adventure」などである必要がありますか?valueそうでない場合は、グループセレクターを属性に直接配置できます。

<label><input type="radio" name="group1" value="div" checked>Show All</label><br>
<label><input type="radio" name="group1" value=".adv">Adventure</label><br>
<label><input type="radio" name="group1" value=".puz">Puzzle</label><br>
<label><input type="radio" name="group1" value=".sho">Shooter</label>

そして、JavaScriptコードは次のように簡略化されます。

function fade( group ) {
    $('#games div')
        .not(group)
        .fadeOut()
        .promise()
        .done( function() {
            console.log( group );
            $('#games ' + group).fadeIn();
        });
}

$('input[name$="group1"]').click(function () {
    fade( $(this).val() );
});

最新のjsfiddle

別の更新...Alexがコメントで指摘しているように、このバージョンのコードでは、[すべて表示]と特定のジャンルの間を行ったり来たりすると、ブロックがジャンプします。

これは、コードの次の行が原因です。

        .not(group)

この更新されたjsfiddleに示すように、その行を削除すると、よりスムーズな遷移が得られます。

于 2013-03-20T17:06:03.600 に答える
1

このフィドルを試してみてください。問題はjQueryセレクターにあり$('#games div')ます。選択は複数のDOM要素を指します。したがってfadeOut()、スコープ内のすべての要素に対して実行され、次にすべての要素の実行に対するコールバックで実行されますfadeIn()。セレクターを追加すると、セレクターが1回だけ実行されるようになります。

$('#games div').filter(":visible")

制限を追加する.filter(":visible")と、表示されているものだけがフェードアウトするようになります(選択範囲の要素が非表示になっている場合よりもフィルターが使用されていない場合は、fadeIn()すぐに起動されます)。また、fadeIn()表示されている選択範囲内のすべての要素が非表示になっている場合にのみ実行されるようにします。

jsfiddle

于 2013-03-20T17:06:45.023 に答える
0

要素のグループを最初にフェードアウトしないようにする必要があります(のようなものを介して.not('.puz'))。そうしないと、jQueryによって最初に要素が再び表示され、次にフェードアウトされます。これを試してください(わかりやすくするために遅延を追加):

$('input[name$="group1"]').click(function () {
    var radio_value = $(this).val();
    if (radio_value == 'Adventure') {
        $('#games div').not('.adv').fadeOut(3000,function () {
            $('#games .adv').fadeIn(3000);
        });
    } else if (radio_value == 'Puzzle') {
        $('#games div').not('.puz').fadeOut(3000,function () {
            $('#games .puz').fadeIn(3000);
        });
    } else if (radio_value == 'Shooter') {
        $('#games div').not('.sho').fadeOut(3000,function () {
            $('#games .sho').fadeIn(3000);
        });
    } else if (radio_value == 'All') {
        $('#games div').fadeOut(3000, function () {
            $('#games div').fadeIn(3000);
        });
    }
});

jsFiddleの例

于 2013-03-20T16:57:31.730 に答える
0

問題は、いくつかの要素でfadeOutを呼び出すと、何度も呼び出されることです。そして、fadeIn をトリガーするコールバックは同じ回数呼び出されます。あなたはそれを必要としません。すべてのフェードアウトが完了したときにのみ、fadeIn の呼び出しを開始する必要があります。

これを行う方法の 1 つは、 $.when .. $ done シーケンスを使用することです。

$.when(
   $('#games div').fadeOut('slow');

).done(function() {
   $('#games .adv').fadeIn();
});

http://api.jquery.com/jQuery.when/
http://api.jquery.com/deferred.done/

于 2013-03-20T17:21:52.710 に答える
0

html5 データ型属性を使用すると簡単に実行できます。チェックアウトjsfiddle

于 2013-03-20T23:29:55.083 に答える