1

アイテムを選択するとキャンバスが再描画される要素と mousemove メソッドがたくさんあります。

function redraw(ctx) { // ctx - canvas context
    if (!needRedraw) 
        return;
    ctx.save();
    ctx.clearRect(0, 0, w, h);
    drawItems(ctx);
    ctx.restore();
}

function drawItems(ctx) {
    var l = nodes.length(); // array of elements for drawing (from 100 to 100000)
    for(var i = 0; i < l; i++) {
        var item = nodes[i];
        ctx.beginPath();
        ctx.strokeStyle = colors(item.type);
        ctx.fillStyle = fill(item);
        ctx.arc(item.x, item.y, item.r, 0, Math.PI * 2, true);
        ctx.fill();
        ctx.stroke();
        ctx.closePath();
    }
}

この非常に高価なプロセスのすべての要素を実行するため、このプロセスを最適化するにはどうすればよいでしょうか? 非同期メソッドを使用できますが、彼を適用する方法がわかりませんか?

4

4 に答える 4

6

への呼び出しはsave、書かれているとおりに何もしませんrestoreclosePathそれらを削除します。

saverestoreキャンバスの状態をすべてコピーし、使用されることはめったにありません。完璧なパフォーマンスの世界でそれらを使用する必要がある唯一の理由は、クリッピング領域をリセットすることです.

パスを 1 つだけ描画し、最後に 1 回だけ塗りつぶします (そしてストロークします)。

このような:

function redraw(ctx) { // ctx - canvas context
    if (!needRedraw) 
        return;
    ctx.clearRect(0, 0, w, h);
    drawItems(ctx);
}

function drawItems(ctx) {
    var l = nodes.length(); // array of elements for drawing (from 100 to 100000)
    ctx.beginPath(); //outside of loop!
    for(var i = 0; i < l; i++) {
        var item = nodes[i];
        ctx.moveTo(item.x+item.r,item.y); // set up subpath to be at the right point
        ctx.arc(item.x, item.y, item.r, 0, Math.PI * 2, true);
    }
    ctx.fill();     //outside of loop!
    ctx.stroke();   //outside of loop!
}

あなたが何をしているかにもよりますが、さらに多くの最適化が必要になる可能性がありますが、それは役立つはずです!

あなたのプロジェクトがうまくいくことを願っています。

于 2012-09-24T16:02:44.743 に答える
2

キャンバス操作の最適化に関する素晴らしい記事があり、その多くはあなたに当てはまるかもしれません。

おそらく最も簡単に開始できるのは、beginPath()andclosePath()呼び出しをループの外に移動し、代わりmoveTo()にセグメント間で使用し、キャンバスを画面外に描画してから表示キャンバスにコピーすることです。

于 2012-09-24T13:20:03.523 に答える
1

パフォーマンスに関するもう 1 つのヒント: Math.PI * 2 の結果をキャッシュします。

そのままでは、javascript はPIオブジェクトから取得し、それを乗算します。値は常に同じになるので、定数を追加するだけです

const PI_TIMES_TWO = 6.28; //or whatever degree of accuracy you want.

...

ctx.arc(item.x, item.y, item.r, 0, PI_TIMES_TWO, true);
于 2012-09-25T02:08:07.313 に答える
1

jsperf はこれがより速いことを示しているので、すべてを逆の順序で描画しても問題ないと仮定して、ループを逆にすることもできます。while ループはさらに高速です。

var i = nodes.length();
while (i--) {
    // ...do stuff...
}
于 2012-09-24T21:11:20.233 に答える