3

ページの上に巨大なキャンバスの長方形を描画しようとしています (ある種のライトボックスの背景)。コードは非常に簡単です:

var el = document.createElement('canvas');
el.style.position = 'absolute';
el.style.top  = 0;
el.style.left = 0;
el.style.zIndex = 1000;
el.width  = window.innerWidth + window.scrollMaxX;
el.height = window.innerHeight + window.scrollMaxY;

...
document.body.appendChild(el);

// and later

var ctx = el.getContext("2d");
ctx.fillStyle = "rgba(0, 0, 0, 0.4)";
ctx.fillRect(0, 0, el.width, el.height);

そして時々 (常にではありません) 最後の行がスローします:

コンポーネントがエラー コードを返しました: 0x80004005 (NS_ERROR_FAILURE) [nsIDOMCanvasRenderingContext2D.fillRect]

画像サイズが原因なのか、それともキャンバスの下にあるコンテンツ タイプ (埋め込みビデオの再生など) が原因なのかを推測していましたが、どうやらそうではないようです。

したがって、この問題を特定および/または解決する方法についてのアイデアを探しています。

4

2 に答える 2

9

nsIDOMCanvasRenderingContext2D.fillRect()実装を見て(そしてそれが呼び出す関数を調べて)、 を返す条件が多すぎるわけではありませんNS_ERROR_FAILUREEnsureSurface()どちらかまたはmThebes->CopyPath()失敗した場合にのみ発生します。そして、次の 2 行EnsureSurface()が問題の原因である可能性が最も高いです。

// Check that the dimensions are sane
if (gfxASurface::CheckSurfaceSize(gfxIntSize(mWidth, mHeight), 0xffff)) {

ここでチェックされているもの:

  • キャンバスの幅も高さも 65535 ピクセルを超えることはできません。
  • Mac OS X では、高さが 32767 ピクセルを超えることはできません (プラットフォームの制限)。
  • キャンバス データ ( width * height * 4) のサイズは 2 GB を超えることはできません。

これらの条件のいずれかに違反EnsureSurface()すると、返さfalseれ、その結果、見た例外が生成されます。上記は実装の詳細であり、いつでも変更される可能性があることに注意してください。それらに依存しないでください。ただし、コードが違反している特定の制限を知ることができる場合があります。

于 2012-09-28T16:40:32.137 に答える
1

try-catch ロジックを適用できます。Firefox は、この少し奇妙な動作をする唯一のブラウザーのようです。

el.width  = window.innerWidth + window.scrollMaxX;
el.height = window.innerHeight + window.scrollMaxY;

// try first to draw something to check that the size is ok
try
{
  var ctx = el.getContext("2d");
  ctx.fillRect(0, 0, 1, 1);
}

// if it fails, decrease the canvas size
catch(err)
{
  el.width = el.width - 1000;
  el.height = el.height - 1000;
}

キャンバスの最大サイズを示す変数は見つかりませんでした。ブラウザごと、デバイスごとに異なります。

最大キャンバス サイズを検出する唯一のクロス ブラウザ メソッドは、キャンバス サイズを縮小するループのようです。エラーが発生しなくなるまで 100px ずつ。ループをテストしましたが、キャンバスの最大サイズを検出するかなり高速な方法です。オーバーサイズのキャンバスに描画しようとしても、他のブラウザではエラーがスローされないため、描画を試みることをお勧めします。赤い四角形でピクセルを読み取り、それが赤かどうかを確認します。

検出パフォーマンスを最大化するには:
- ループ中は速度を最大化するためにキャンバスを DOM の外に出す必要があります
- 開始サイズを 32,767px と思われる既知の最大値に設定します (SO: <canvas> 要素の最大サイズ)
- あなたは最大サイズをフォークする、よりインテリジェントなループを作成できます。たとえば、最初の大きな減少ステップ (例: 1000px) を使用し、受け入れられたサイズに達すると、サイズを 500px ずつ増加させようとします。これが受け入れられるサイズである場合は、250px ずつ増やします。このようにして、最小量の試行で最大値を見つける必要があります。

于 2015-06-01T21:17:45.720 に答える