画像のsrcをデータURLに設定すると、すぐに利用できるようになるはず?
質問
以下の(壊れやすい)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" (上記の質問より) は、正しい動作を保証する唯一の方法です。
もし誰かがこれを議論している仕様を見つけることができれば、私は喜んでその答えを代わりに受け入れるでしょう。
関連
-
[解決済み】HTML5キャンバスの画像サイズを変更する
-
[解決済み] Javascript / jQueryでAndroid端末を検出する。
-
[解決済み] Chromeの拡張機能開発にWebStormを使用するにはどうすればよいですか?
-
[解決済み] モデルフェッチ時に1をtrueに、0をfalseに変換する方法
-
[解決済み] <ng-content>が空かどうかを確認する方法は?(これまでのAngular 2+で)
-
[解決済み] HTML要素にスクロールバーがあるかどうかをチェックする
-
[解決済み] javascriptのキャンバスで画像をリサイズする (スムーズ)
-
[解決済み] jQueryのバージョン1、バージョン2、バージョン3の違いは何ですか?[クローズド]
-
[解決済み] V8 Javascript エンジンのスタンドアロン実行
-
[解決済み] URL からリモート画像の幅と高さを取得する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] javascriptから画像を読み込む
-
[解決済み] AngularJSのエラーです。Cross Origin リクエストはプロトコルスキーム http, data, chrome-extension, https に対してのみサポートされています。
-
[解決済み] JavaScriptで次の要素/前の要素を取得しますか?
-
[解決済み] Google maps API V3 - 同一地点に複数のマーカーを設置する。
-
[解決済み] javascript の関数から `undefined` と `null` のどちらを返すのが良いのでしょうか?
-
[解決済み] 文字列が空白であるかどうかをチェックする
-
[解決済み] データURLからキャンバスへの画像描画
-
[解決済み] jQueryを使用して、すべてのクリックイベントハンドラを削除するにはどうすればよいですか?
-
[解決済み] Node.jsのES6クラスをrequireで作る
-
[解決済み] jQueryのバージョン1、バージョン2、バージョン3の違いは何ですか?[クローズド]