76

次の(壊れやすい)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ページをローカルで開いて(url)、サーバーからロードすることで、すべてが機能していることを示しました。高さと幅が正しく、キャンバスの描画が機能し、起動します。file:///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 = '...';
4

2 に答える 2

53

これがどのように動作するかについての仕様はまだ誰も見つけていないので動作に満足する必要があります。以下は私のテストの結果です。

            | 画像データは正しく使用できますか| srcの後にonloadコールバックセットを実行します
            | srcを設定した後?| 変更されたまま呼び出されますか?
------------ + ----------------------------- + ------- ------------------------------
Safari 5 | はい| はい                
------------ + ----------------------------- + ------- ------------------------------
Chrome 8 | **いいえ**(最初のページの読み込み)、ただし| はい                
FireFox 3.6 | はい、その後(キャッシュ)|                                     
------------ + ----------------------------- + ------- ------------------------------
IE8 | はい(32kBデータ制限)| はい         
------------ + ----------------------------- + ------- ------------------------------
IE9b | はい| **いいえ**              
------------ + ----------------------------- + ------- ------------------------------

要約すれば:

  • data-uriを設定した直後に画像データが利用可能になるとは限りません。onloadイベントを待つ必要があります。
  • onloadIE9のため、を設定した後にハンドラーを設定してsrc、それが呼び出されることを期待することはできません。
  • 「安全にプレイする」(上記の質問から)の推奨事項は、正しい動作を保証する唯一の方法です。

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

于 2011-01-26T16:33:12.603 に答える
7

ブラウザのレンダリングエンジンに制御を戻した後、テストはtrueFF4b9およびChromium8.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ます。

どちらの場合も、ページをリロードした後でのみ、画像が最初に表示されることはありません。

于 2011-01-23T21:50:35.653 に答える