2012-06-22 22 views
5

私はちょうどHTML5キャンバスで遊んで始めました。私はそれを使っていくつかのゲームを作りたいと思っていました。しかし、できるだけ早く私は、マウスがそれに座標レンダリングを開始し、それが近く停止に粉砕:38行といくつかのテキスト、ありません、それを処理することができるはずのレンダリング私はすべてのHTML5キャンバスの再描画が非常に遅い

http://jsfiddle.net/mnpenner/zHpgV/

でしたか?

何か間違っていますか?私は30 FPSでレンダリングできるようにしたいと思いますが、このようなものについては、私はそれが1000秒を描くことができると期待しています。

私は仕事に間違ったツールを使用していますか?タスクのためにWebGLが起動していますか?なぜ、他のものよりもずっと遅いのですか?

String.prototype.format = function() { 
 
    var args = arguments; 
 
    return this.replace(/\{(\d+)\}/g, function(m, n) { 
 
     return args[n]; 
 
    }); 
 
}; 
 
var $canvas = $('#canvas'); 
 
var c = $canvas[0].getContext('2d'); 
 
var scale = 20; 
 
var xMult = $canvas.width()/scale; 
 
var yMult = $canvas.height()/scale; 
 
var mouseX = 0; 
 
var mouseY = 0; 
 
c.scale(xMult, yMult); 
 
c.lineWidth = 1/scale; 
 
c.font = '1pt Calibri'; 
 

 
function render() { 
 
    c.fillStyle = '#dcb25c'; 
 
    c.fillRect(0, 0, scale, scale); 
 
    c.fillStyle = '#544423'; 
 
    c.lineCap = 'square'; 
 
    for (var i = 0; i <= 19; ++i) { 
 
     var j = 0.5 + i; 
 
     c.moveTo(j, 0.5); 
 
     c.lineTo(j, 19.5); 
 
     c.stroke(); 
 
     c.moveTo(0.5, j); 
 
     c.lineTo(19.5, j); 
 
     c.stroke(); 
 
    } 
 
    c.fillStyle = '#ffffff'; 
 
    c.fillText('{0}, {1}'.format(mouseX, mouseY), 0.5, 1.5); 
 
} 
 
render(); 
 
$canvas.mousemove(function(e) { 
 
    mouseX = e.clientX; 
 
    mouseY = e.clientY; 
 
    render(); 
 
});
<canvas id="canvas" width="570" height="570"></canvas>

答えて

7

ここでコードははるかに優れています。

  • 連続ではなく、停止してbeginPathで新しいパスを作成するためのパスに追加する:

    http://jsfiddle.net/zHpgV/3/

    は、ここで私は変わっあなたが考慮すべき事柄の内訳です。これは、これまでのところ最大のパフォーマンスキラーです。あなたは決してクリアされない何千ものラインセグメンテーションを持つパスで終わります。

  • 初期化時に一度行う必要がある場合に限り、同じパスを繰り返し作成します。つまり、renderの中で呼び出す必要があるのはstrokeです。 lineTo/moveToに再度電話する必要はなく、確かに連続して電話する必要はありません。 1.
  • が背景を再描画の代わりに、注1の上に及び

上のラインキャップを設定するCSSの背景
  • を設定するループ
  • のために内部で撫でる1つのパス
  • のために二回撫でる注意を参照してください。 :アプリケーションに複数のパスがある場合は、変更されないため、このようなパスをキャッシュする必要があります。私はそれを行う方法についてのチュートリアルを持っていますhere

    もちろん、背景を作るためにこれをやっているのなら、それはpngとして保存する必要があり、CSSの背景イメージを使用する必要があります。そのよう

    http://jsfiddle.net/zHpgV/4/が突然あなたのルーチンをレンダリングはかなり小さいです:

    function render() { 
        c.clearRect(0, 0, scale, scale); 
        c.fillText('{0}, {1}'.format(mouseX, mouseY), 0.5, 1.5); 
    } 
    
  • +0

    私は道がそれを働いたことを知らなかった!私は、 'path'オブジェクトを持っている方が直感的だったと思います。なぜ今はとても遅かったのか分かります、ありがとう! – mpen

    +3

    HTML5 Canvas仕様にパスオブジェクトが追加されました。今後、パスを作成して 'drawPath'を呼び出すことができます。しかし、ブラウザはまだそれを実装していないし、あなたがそれを利用できるようになるまで数ヶ月かかるかもしれない。いつか買う! –

    7

    あなたはすべてのアニメーションフレームにグリッド全体を描画する必要はありません。それを別の基底のキャンバスに置きます(レイヤーと呼ぶのが一般的ですが、別々のキャンバス要素です)ので、座標のみを再描画することができます。

    <div id="canv"> 
    <canvas id="bgLayer" width="500" height="500" style="z-index: 0"></canvas> 
    <canvas id="fgLayer" width="500" height="500" style="z-index: 1"></canvas> 
    </div> 
    

    ここはthe example私はレイヤードキャンバスで遊んでいます。下のキャンバスに描かれたテーブルは、上のキャンバスにボールが描かれています。それは単なる遊び場なので、そこでは修正や最適化が大変です。たとえば、すべてのボールを別の隠しキャンバスに1回だけ描​​画し、getImageData/putImageDataを使用してパフォーマンスを向上させるなどです。

    また、requestAnimationFrameを使用してキャンバスを更新することをお勧めします。あなたの例はマウスの動きごとに描かれていますが、これはもっと頻繁に必要です(もちろんマウスが動く時)。

    キャンバスのパフォーマンスを向上させるには、良いarticleがあります。また、この件に関してはSO postがあります。

    +0

    あなたは文字通りcanvas要素をレイヤー意味を理解するためにしばらくかかりました。私は "レイヤー"はキャンバスの文脈の中のコンセプトだと思っていました。それは良いアイデアです。ヒントをありがとう! – mpen

    +0

    申し訳ありませんが、他の人を混乱させないように変更しました。 –

    +1

    これは良いコメントですが、私にはこの場合見つけられない別の問題があります。非常に高速なアニメーションで、はるかに複雑なものを描きますが、ダブルバッファリングについても気にする必要はありません。 –

    9

    私はこのコードの遅さに驚きました。私は非常に高速なアニメーションで、はるかに複雑なものを描きながら、ダブルバッファリングについても悩ますことはありません。

    私はもう少し見て、期待どおりのバグを見つけました。

    主な問題は、描画パスの累積です。

    1つのパスを描画するたびにc.beginPath();を追加します。

    ここにはfast rendering of the same thingがあり、今すぐ飛ぶことが証明されています。

    キャンバスドローブは、であり、アニメーションに使用することができます。

    関連する問題