画像SRCをデータURLに設定する必要がありますか?
-
23-10-2019 - |
質問
次の(壊れやすい)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)では、ブラウザの起動後にページを読み込むと、設定後すぐに高さ/幅が正しくないことが示されています。 drawImage()
失敗します。 ( onload
ただし、ハンドラーは発射します。)ただし、ページを再度ロードすると、設定後すぐに幅/高さが正しいことを示し、 drawImage()
働く。 Firefoxは、データURLの内容を画像としてキャッシュし、同じセッションで使用するとすぐに利用できるように見えます。
Chrome V8(OS X)では、Firefoxと同じ結果が表示されます。画像はすぐには利用できませんが、データURLから非同期的に「ロード」するのに時間がかかります。
上記のブラウザが機能する、または機能しないことの実験的証明に加えて、これがどのように振る舞うかについての仕様へのリンクが大好きです。これまでのところ、私のGoogle-Fuはタスクに任されていません。
安全にプレイします
上記が危険な理由を理解していない人のために、このような画像を安全に使用する必要があることを知ってください。
// 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 = '...';
解決
誰もこれがどのようであるかについての仕様をまだ見つけていないので 想定 振る舞うには、それがどのようにあるかに満足する必要があります します 振る舞う。以下は私のテストの結果です。
| is image data usable right | does onload callback set after src | after setting src? | is changed still get invoked? ------------+-----------------------------+------------------------------------- Safari 5 | yes | yes ------------+-----------------------------+------------------------------------- Chrome 8 | **no** (1st page load), but | yes FireFox 3.6 | yes thereafter (cached) | ------------+-----------------------------+------------------------------------- IE8 | yes (32kB data limit) | yes ------------+-----------------------------+------------------------------------- IE9b | yes | **no** ------------+-----------------------------+-------------------------------------
要約すれば:
- Data-URIを設定した直後に画像データが利用可能になるとは想定できません。あなたは待つ必要があります
onload
イベント。 - IE9のため、設定することはできません
onload
設定後のハンドラーsrc
そして、それが呼び出されることを期待してください。 - の推奨事項 「安全に遊ぶ」 (上記の質問から)正しい動作を確保する唯一の方法です。
誰かがこれについて議論する仕様を見つけることができれば、代わりに彼らの答えを喜んで受け入れます。
他のヒント
ブラウザのレンダリングエンジンをコントロールした後、テストレポート true
FF 4B9およびChromium 8.0.552.237で。これらの部分を変更しました:
img.onload = function(){ // put this above img.src = …
document.getElementById('onload').innerHTML = 'yes';
};
img.src = img_src;
…
window.setTimeout(function () { // put this inside setTimeout
document.getElementById('wh').innerHTML = (img.height==img.width) && (img.height==128);
}, 0);
アップデート: はい、私はこの「答え」がコメントのようなものであることを理解していますが、それを指摘したかっただけです。そして、テスト後、再現性のある結果が得られます。
- それなし
setTimeout
, 、両方のブラウザで私が取得しますfalse
初めてページを開くときtrue
打った後にのみ F5. 。キャッシュを明示的にクリアした後、両方とも言いますfalse
再びリロードした後。 - と
setTimeout
幅/高さのテストは常に発生しますtrue
.
どちらの場合も、ページをリロードした後にのみ、画像が初めて表示されません。