3

フェードインおよびフェードアウトする視覚的な「タイル」を作成するこのコードを作成しました。しかし、現時点では、パフォーマンスに少し問題があります。

ほとんどのブラウザーは問題なくコードを実行していますが (特に Firefox)、しばらくすると (しばらく = 15 秒程度) Safari のようなブラウザーでは問題が発生します。

私の再帰関数(遅延で自分自身を永遠に呼び出すchangeopacityという名前の関数)が原因だと思いますか?またはそれは?

とにかく問題は、このコードがほとんどのブラウザーにとって非常に重いことです。このコードのパフォーマンスを向上させるにはどうすればよいですか? 何かご意見は?(コード例はいいでしょう)ありがとう:-)

実際のコード:

$(document).ready(function () {

    var aniduration = 2000;
    var tilesize = 40;

    createtable(tilesize);



    $(".tile").each(function (index, domEle) {
        var randomdelay = Math.floor(Math.random() * 3000);
        setTimeout(function () {
            changeopacity(aniduration, domEle);
        }, randomdelay);
    });



    $("td").click(function () {
        clickanimation(this, 9);
    });

    $("td").mouseenter(function () {
        var element = $(this).find("div");
        $(element).clearQueue().stop();
        $(element).animate({opacity: "0.6"}, 800);
    });


    $("td").css("width", tilesize + "px").css("height", tilesize + "px");



});

function createtable(tilesize) {
    var winwidth = $(window).width();
    var winheight = $(window).height();
    var horztiles = winwidth / tilesize;
    var verttiles = winheight / tilesize;


for (var y = 0; y < verttiles; y++)
{
    var id = "y" + y;
    $("#tbl").append("<tr id='" + id + "'></tr>");

    for (var x = 0; x < horztiles; x++)
    {
        $("#" + id).append("<td><div class='tile' style='opacity: 0; width: " + tilesize + "px; height: " + tilesize + "px;'></div></td>");
    }
}   
}

function changeopacity(duration, element){
    var randomnum = Math.floor(Math.random() * 13);
    var randomopacity = Math.floor(Math.random() * 7);
    var randomdelay = Math.floor(Math.random() * 1000);

    if ($(element).css("opacity") < 0.3)
    {
        if (randomnum != 4)
        {
            if ($(element).css("opacity") != 0)
            animation(element, 0, duration, randomdelay);
        }
        else
        {
            animation(element, randomopacity, duration, randomdelay);
        }
    }
    else
    {
        animation(element, randomopacity, duration, randomdelay);
    }

    setTimeout(function () {
        return changeopacity(duration, element);
    }, duration + randomdelay);
}

function animation(element, randomopacity, duration, randomdelay){
    $(element).clearQueue().stop().delay(randomdelay).animate({opacity: "0." + randomopacity}, duration);
}


function clickanimation(column, opacitylevel) {
        var element = $(column).find("div");
        $(element).clearQueue().stop();
        $(element).animate({"background-color": "white"}, 200);
        $(element).animate({opacity: "0." + opacitylevel}, 200);
        $(element).delay(200).animate({opacity: "0.0"}, 500);
        //$(element).delay(600).animate({"background-color": "black"}, 500);
}
4

2 に答える 2

2

素敵なアニメーション:-)しかし、私はいくつかのバグと可能な改善を見つけました:

  • ウィンドウのサイズ変更時にテーブルが再構築されません。バグか機能かわからない:-)
  • 委任されたイベントを使用します。あなたにはたくさんの要素があり、すべてのイベントハンドラーはコストがかかります。mouseenter残念ながら、これはバブル以外のイベントでは機能しません。
  • withとheightにインラインスタイルを使用しないと便利です。これらは変更されません。divにとって、彼らはとにかくsuperflouosです。
  • これらすべての要素にIDがある理由がわかりません。html文字列の構築はもっと簡潔かもしれません。

  • 要素をキャッシュします!!! ほぼすべての変数でコンストラクターを使用してjQuery、新しいインスタンスを構築しています。それらを再利用するだけです!

  • あなたのchangeopacity関数は少し奇妙に見えます。不透明度が0.3未満の場合、13分の1の確率でゼロにアニメートできますか?それはもっと厳格に表現されるかもしれません。また、毎回domから不透明度を読み取る代わりに、不透明度を変数にキャッシュすることもできます。

  • およびその他の定数を引数として渡す理由はありdurationません。これらは変更されることはなく、グローバルスコープから使用できます。

  • タイムアウトを使用する代わりに、メソッドの完全なコールバックをanimate使用する必要があります。タイムアウトは決して正確ではなく、ここで干渉して(マイナーな)問題を引き起こす可能性さえあります。

var duration = 2000,
    tilesize = 40,
    clickopacity = 0.9;

$(document).ready(function () {

    filltable($("#tbl"), tilesize)
      .on("click", "td", clickanimation);

    $(".tile").each(function() {
        changeopacity($(this));
    });

    $("#tbl div").mouseenter(function () {
        $(this).clearQueue()
               .stop()
               .animate({opacity: "0.6"}, 800);
    });
});

function filltable(tbl, tilesize) {
    var win = $(window).width();
    var horztiles = win.width() / tilesize;
    var verttiles = win.height() / tilesize;

    for (var y = 0; y < verttiles; y++) {
        var tr = "<tr>";
        for (var x = 0; x < horztiles; x++)
            tr += "<td style='width:"+tilesize+"px;height:"+tilesize+"px;'><div class='tile' style='opacity:0;'></div></td>");
        tbl.append(tr+"</tr>");
    }
    return tbl;
}

function changeopacity(element) {
    var random = Math.floor(Math.random() * 13);
    var opacity = Math.floor(Math.random() * 7);
    var delay = Math.floor(Math.random() * 1000);

    if (element.css("opacity") < 0.3 && random != 4)
        opacity = 0;

    element.clearQueue().stop().delay(delay).animate({
        opacity: "0." + opacity
    }, duration, function() {
        changeopacity(element);
    });
}

function clickanimation() {
    $(this.firstChild)
      .clearQueue()
      .stop()
      .animate({"background-color": "white"}, 200)
      .animate({opacity: "0." + clickopacity}, 200)
      .delay(200).animate({opacity: "0.0"}, 500);
    //.delay(600)
    //.animate({"background-color": "black"}, 500);
}
于 2012-07-19T20:58:56.593 に答える
2

一番の問題はsetTimeout、ページ上のすべてのセルに対して 1 つを作成していることです。これを処理できる唯一のブラウザーは Internet Explorer であり、多くの CSS 変更により再描画が遅くなるため失敗します。

独自のイベント スケジューラをプログラミングすることを強くお勧めします。私が大学のプロジェクトで使用したこのようなもの:

var timer = {
    length: 0,
    stack: {},
    timer: null,
    id: 0,
    add: function(f,d) {
        timer.id++;
        timer.stack[timer.id] = {f: f, d: d, r: 0};
        timer.length++;
        if( timer.timer == null) timer.timer = setInterval(timer.run,50);
        return timer.id;
    },
    addInterval: function(f,d) {
        timer.id++;
        timer.stack[timer.id] = {f: f, d: d, r: d};
        timer.length++;
        if( timer.timer == null) timer.timer = setInterval(timer.run,50);
        return timer.id;
    },
    remove: function(id) {
        if( id && timer.stack[id]) {
            delete timer.stack[id];
            timer.length--;
            if( timer.length == 0) {
                clearInterval(timer.timer);
                timer.timer = null;
            }
        }
    },
    run: function() {
        var x;
        for( x in timer.stack) {
            if( !timer.stack.hasOwnProperty(x)) continue;
            timer.stack[x].d -= 50;
            if( timer.stack[x].d <= 0) {
                timer.stack[x].f();
                if( timer.stack[x]) {
                    if( timer.stack[x].r == 0)
                        timer.remove(x);
                    else
                        timer.stack[x].d = timer.stack[x].r;
                }
            }
        }
    }
};

次に、を使用する代わりに、同じ引数setTimeoutで呼び出します。timer.add同様に、代わりにsetIntervalを呼び出すことができますtimer.addInterval

これにより、好きなだけタイマーを持つことができ、それらはすべて単一の で実行されるsetIntervalため、ブラウザーの問題が大幅に少なくなります。

于 2012-07-19T20:44:36.347 に答える