0

全て、

私は「クレジットモジュール」(ゲームのクレジットシステムに似ています)を持っています。これは、ユーザーがアクションを実行すると、追加または減算されるコストで内部divを作成し、ユーザーが最後のアクションのコストを確認できるようにします。

問題:関数が1回呼び出される限り、すべてが正常に機能します。ユーザーが複数のアクションをすばやく実行すると、setTimeout関数(コストdivをアニメーション化してから削除することになっています)が実行されません。関数の2番目のインスタンスは、最初のsetTimeout関数をリセットしているようです。

(function()
{

$("#press").on("click", function(){creditCost(50)});

function creditCost(x)
{
var eParent = document.getElementById("creditModule");
// following code creates the div with the cost
eParent.innerHTML += '<div class="cCCost"><p class="cCostNo"></p></div>';
var aCostNo = document.getElementsByClassName("cCostNo");
var eLatestCost = aCostNo[aCostNo.length - 1];
// following line assigns variable to above created div '.cCCost'
var eCCost = eLatestCost.parentNode;
// cost being assigned
eLatestCost.innerHTML = x;
$(eCCost).animate ({"left":"-=50px", "opacity":"1"}, 250, "swing");
// following code needs review... not executing if action is performed multiple times quickly
setTimeout(function()
{
    $(eCCost).animate ({"left":"+=50px", "opacity":"0"}, 250, "swing", function ()
    {
        $(eCCost).remove();
    })  
}, 1000);
}

})();

jsfiddle、CSSを失礼します

4

3 に答える 3

2
eParent.innerHTML += '<div class="cCCost"><p class="cCostNo"></p></div>';

悪い線です。これにより、要素のがリセットされ、innerHTMLDOM全体が再作成され、前の呼び出しで参照された要素が破棄され、タイムアウトが失敗します。詳細については、 「innerHTML + = ...」と「appendChild(txtNode)」を参照してください。利用可能なときにjQueryを使用してみませんか?

function creditCost(x) {
    var eParent = $("#creditModule");
    // Create a DOM node on the fly - without any innerHTML
    var eCCost = $('<div class="cCCost"><p class="cCostNo"></p></div>');

    eCCost.find("p").text(x); // don't set the HTML if you only want text

    eParent.append(eCCost); // don't throw over all the other children
    eCCost.animate ({"left":"-=50px", "opacity":"1"}, 250, "swing")
          .delay(1000) // of course the setTimeout would have worked as well
          .animate ({"left":"+=50px", "opacity":"0"}, 250, "swing", function() {
               eCCost.remove();
          });  
}
于 2012-08-25T16:18:43.023 に答える
1

アニメーションを開始し、タイムアウトをスケジュールして、ユーザーがすばやくクリックした場合にその操作の途中で変更されるDOM要素を処理します。これを修正するには、次の2つのオプションがあります。

  1. 前のアニメーションを台無しにしないように、安全のために2回目のクリックで新しいアイテムを追加します。
  2. 新しいアニメーションを開始する前に、前のアニメーションを停止してクリーンアップします。

次のコードの書き直しと簡略化により、どちらの動作も実装できます。コードの最初の行を含めるかどうかによって、動作#1または#2を取得するかどうかを制御します。

function creditCost(x) {
    // This first line of code is optional depending upon what you want to happen when the 
    // user clicks rapid fire.  With this line in place, any previous animations will
    // be stopped and their objects will be removed immediately
    // Without this line of code, previous objects will continue to animate and will then
    // clean remove themselves when the animation is done
    $("#creditModule .cCCost").stop(true, false).remove();

    // create HTML objects for cCCost
    var cCCost = $('<div class="cCCost"><p class="cCostNo">' + x + '</p></div>');
    // add these objects onto end of creditModule
    $("#creditModule").append(cCCost);

    cCCost
        .animate ({"left":"-=50px", "opacity":"1"}, 250, "swing")
        .delay(750)
        .animate({"left":"+=50px", "opacity":"0"}, 250, "swing", function () {
            cCCost.remove();
        });  
    }
})();

注:からに変更しsetTimeout().delay()、今後のすべてのアクションを簡単に停止できるようにしました。setTimeout()を使用したままの場合は、から返されたtimerIDを保存して、を呼び出すことができるようにする必要がありますclearTimeout()。を使用して.delay()、jQueryはこれを行います。

于 2012-08-25T16:16:52.487 に答える
0

主にjavascriptを使用したい人のためにコードを更新しました。Jsfiddle、CSSを失礼します。

function creditCost(x)
{
    var eParent = document.getElementById("creditModule");
    var eCCost = document.createElement("div");
    var eCostNo = document.createElement("p");
    var sCostNoTxt = document.createTextNode(x);
    eCCost.setAttribute("class","cCCost");
    eCostNo.setAttribute("class","cCostNo");
    eCostNo.appendChild(sCostNoTxt);
    eCCost.appendChild(eCostNo);
    eParent.insertBefore(eCCost, document.getElementById("creditSystem").nextSibling);
    $(eCCost).animate ({"left":"-=50px", "opacity":"1"}, 250, "swing");
    setTimeout(function()
    {
        $(eCCost).animate ({"left":"+=50px", "opacity":"0"}, 250, "swing", function ()
        {
            $(eCCost).remove();
        })  
    }, 1000);
}
于 2012-08-26T05:41:18.730 に答える