1. ホーム
  2. javascript

画像のsrcをデータURLに設定すると、すぐに利用できるようになるはず?

2023-10-02 21:08:06

質問

以下の(壊れやすい)JavaScriptのコードを考えてみてください。

var img = new Image;
img.src = "data:image/png;base64,..."; // Assume valid data

// Danger(?) Attempting to use image immediately after setting src
console.log( img.width, img.height );
someCanvasContext.drawImage( img, 0, 0 );

// Danger(?) Setting onload after setting src
img.onload = function(){ console.log('I ran!'); };

質問(複数可)

  • 画像の幅と高さはすぐに正しく表示されるべきですか?
  • キャンバスの描画は即座に動作する必要がありますか?
  • キャンバスの描画は onload コールバック (src が変更された後に設定) を呼び出すべきでしょうか?

実験的なテスト

を作成しました。 簡単なテストページ を同様のコードで作成しました。Safari の最初のテストでは、HTML ページをローカルに開いて ( file:/// url) で開き、サーバーから読み込んだところ、すべてがうまくいきました。高さと幅が正しく、キャンバスの描画もうまくいきました。 onload も発火します。

Firefox v3.6 (OS X) で、ブラウザ起動後にページを読み込むと、設定直後にheight/widthが正しく表示されない。 drawImage() が失敗する。(このとき onload ハンドラは実行されます)。しかし、ページを再度読み込むと、設定直後から幅と高さが正しくなっており drawImage() が動作していることがわかります。Firefox がデータ URL の内容を画像としてキャッシュし、同じセッションで使用するときにすぐに利用できるようにしているようです。

Chrome v8 (OS X) では、Firefox と同じ結果が得られました。画像はすぐには利用できませんが、データ URL から非同期に「ロード」するのに時間がかかります。

上記が動作する、または動作しないブラウザの実験的な証明に加えて、私は本当にこれがどのように動作することになっているかについての仕様へのリンクが欲しいです。これまでのところ、私の Google の腕前では、このタスクに対応できていません。

安全に遊ぶ

なぜ危険なのかわからないという方のために、安全のためにこのような画像を使いましょうということをお伝えします。

// First create/find the image
var img = new Image;

// Then, set the onload handler
img.onload = function(){
  // Use the for-sure-loaded img here
};

// THEN, set the src
img.src = '...';

どのように解決するのですか?

どのように解決するかについては、まだ誰も仕様を見つけていません。 と思われる がどのように動作するかについての仕様はまだ見つかっていません。 する の動作に満足しなければなりません。以下は、私のテスト結果です。

            | 画像データは正しく使えるか|オンロードコールバックはsrcの後に設定されているか
            | srcを設定した後か?     

|onloadのコールバックはsrcの後に設定されるか? ------------+-----------------------------+------------------------------------- サファリ5|はい|はい ------------+-----------------------------+------------------------------------- Chrome 8|**いいえ** (最初のページロード), しかし、|はい。 FireFox 3.6 | 以降は、はい(キャッシュされる)|。 ------------+-----------------------------+------------------------------------- IE8|はい(32kB データ制限)|はい ------------+-----------------------------+------------------------------------- IE9b| はい| **いいえ** です。 ------------+-----------------------------+-------------------------------------

まとめると

  • data-uriを設定した直後に画像データが利用可能になるとは考えられず、その時点で onload イベントを待つ必要があります。
  • IE9 のため onload ハンドラを設定した後に src を設定し、それが呼び出されることを期待します。
  • の推奨事項は "Playing it Safe" (上記の質問より) は、正しい動作を保証する唯一の方法です。

もし誰かがこれを議論している仕様を見つけることができれば、私は喜んでその答えを代わりに受け入れるでしょう。