Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。

キャンバスの最適化

<canvas> 要素は、ウェブで 2 次元グラフィックを描画するためにもっとも広く使用されているツールのひとつです。しかし、ウェブサイトやアプリがキャンバス API の限界付近まで使用するようになって、パフォーマンスが悪化するようになりました。この記事では、キャンバス要素の使用を最適化して、グラフィックを確実に改善するための提案を行います。

パフォーマンスに関する TIPS

キャンバスのパフォーマンスを向上させるための TIPS 集を以下に掲載します。

同様のプリミティブや繰り返し使用するオブジェクトをオフスクリーンキャンバスで事前にレンダリングする

アニメーションフレーム毎に同じ描画操作を繰り返していることに気づいたら、あらかじめオフスクリーンキャンバスに描画しておくことを検討しましょう。そして、必要な時に本来のキャンバスにオフスクリーン画像を、最初の場所で生成したときのステップなしで描画することができます。

js
myCanvas.offscreenCanvas = document.createElement("canvas");myCanvas.offscreenCanvas.width = myCanvas.width;myCanvas.offscreenCanvas.height = myCanvas.height;myCanvas.getContext("2d").drawImage(myCanvas.offScreenCanvas, 0, 0);

浮動小数点数値の座標を避けて整数を使用

キャンバスで整数以外の値を使用してオブジェクトを描画すると、サブピクセルレンダリングを実行します。

js
ctx.drawImage(myImage, 0.3, 0.5);

これはアンチエイリアス効果を生成するために、ブラウザーに追加の計算処理を強制します。これを避けるために、たとえばdrawImage() を呼び出す際にMath.floor() を使用して、すべての座標で端数処理を行ってください。

drawImage で画像の拡大縮小を行わない

drawImage() でいつも画像の拡大縮小処理を行うのではなく、さまざまなサイズの画像をオフスクリーンキャンバスでキャッシュしてください。

複雑なシーンでは複数レイヤーのキャンバスを使用する

アプリケーションでは、一部のオブジェクトは頻繁に動かしたり変更したりする必要があるのに対し、他のものは比較的静止していることが分かるかもしれません。この場合に可能な最適化は、複数の<canvas> 要素を使用してアイテムをレイヤー化することです。

例えば、 UI があるゲームが最上位にあり、中間にゲームプレイの動作があり、最下位に静止した背景があるとします。この場合、ゲームを3つの<canvas> レイヤーに分割することができます。 UI はユーザーの入力のみに基づいて変化し、ゲームプレイレイヤーはフレーム毎に変化し、背景は基本的に変化しないままでいます。

html
<div>  <canvas width="480" height="320"></canvas>  <canvas width="480" height="320"></canvas>  <canvas width="480" height="320"></canvas></div><style>  #stage {    width: 480px;    height: 320px;    position: relative;    border: 2px solid black;  }  canvas {    position: absolute;  }  #ui-layer {    z-index: 3;  }  #game-layer {    z-index: 2;  }  #background-layer {    z-index: 1;  }</style>

大きな背景画像に CSS を使用する

静止した背景画像がある場合は、ただの<div> に CSS のbackground プロパティを使用し、キャンバスの下に配置することで描画することができます。これにより、大きな画像を毎回キャンバスに描画する処理を避けます。

CSS 座標変換を使用してキャンバスを拡大縮小する

CSS 座標変換は、 GPU を使用しますのでより高速です。もっともよいのは拡大縮小しないことですが、そうでなければ大きなキャンバスを縮小するよりも小さなキャンバスを拡大したほうが良好です。

js
const scaleX = window.innerWidth / canvas.width;const scaleY = window.innerHeight / canvas.height;const scaleToFit = Math.min(scaleX, scaleY);const scaleToCover = Math.max(scaleX, scaleY);stage.style.transformOrigin = "0 0"; // 左上から拡大stage.style.transform = `scale(${scaleToFit})`;

透過をやめる

アプリケーションがキャンバスを使用していて背後のものを透過させる必要がない場合は、HTMLCanvasElement.getContext() で描画コンテキストを生成する際にalpha オプションをfalse に設定しましょう。この情報を使用してブラウザーが描画を最適化する可能性があります。

js
const ctx = canvas.getContext("2d", { alpha: false });

高解像度のディスプレイでの変倍

高解像度のディスプレイでは、キャンバスのアイテムがぼやけて見えることがあります。多くの解決策がありますが、まず簡単な方法は、キャンバスの属性、スタイル、およびコンテキストのスケールを使用してキャンバスのサイズを同時に変倍することです。

js
// DPR とキャンバスの大きさを取得const dpr = window.devicePixelRatio;const rect = canvas.getBoundingClientRect();// キャンバスの「実際の」大きさを設定canvas.width = rect.width * dpr;canvas.height = rect.height * dpr;// 正しい描画操作を保証するためにコンテキストの変倍ctx.scale(dpr, dpr);// キャンバスの「描画される」大きさを設定canvas.style.width = `${rect.width}px`;canvas.style.height = `${rect.height}px`;

その他の TIPS

  • キャンバスの呼び出しをひとまとめにします。たとえば、複数に分割した線分ではなくポリラインを描画します。
  • 不必要なキャンバスの状態変更を避けます。
  • 新しい状態の全体を描画せずに、スクリーンの差分だけを描画します。
  • 可能な限りshadowBlur プロパティを避けます。
  • 可能な限りテキストレンダリングを避けます。
  • キャンバスをクリアーする別の方法を試します (clearRect()fillRect() 対キャンバスのリサイズ)
  • アニメーションでsetInterval の代わりにwindow.requestAnimationFrame() を使用します。
  • 高負荷な物理演算ライブラリーに注意してください。

関連情報

Help improve MDN

Learn how to contribute.

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp