IE6でスワップした画像が描画されない

2007.07.18 / javascript

普段、prototype.jsの$関数(document.getElementByIdのショートカット関数)にどっぷりハマっていると、痛い目にあいますよ、な話。

JavaScriptで画像をスワップさせようとする場合、どうするでしょう?Ajaxゴリゴリなコードを書くことが多い僕はついつい$関数を利用して

$('hoge').innerHTML = 'foo'

のノリで

$('hoge').src = 'foo.jpg'

な、コードを書いてしまいます。

このコードは正しいことは正しい、、のですが、実際はうまく動作しません。厳密に言うと、IE6でのみ想定したような動作をしない場合があります。

たとえば、いくつかタブのように画像を並べて、クリックしたタブの画像だけをアクティブっぽい画像に、その他のタブの画像は非アクティブな画像にする、とします。その際に上記のようなコードを利用すると、IE6の場合のみ、スワップさせた画像領域が何も描画されなくなる場合があります。いきなり真っ白になって「え??」と思い、右クリック→画像の表示、を行うと、そこで初めて画像が描画されます。要するにスワップした画像のレンダリングが追いついていないのです。これはIE7では(僕が体験した限り)起きることはありません。また、IE6でもスワップ対象の画像数が1つだとほぼ起きないですが、2つ以上になると途端に描画が不安定になります。

「キャッシュに残せばいいんじゃない?」と、いうことで、onload時にスワップ対象画像を全部loadさせる手もあるかと思いますが、それでも自体は(ほぼ)変わりません。「じゃぁどうすればいいの?」と、いう話になるのですが、困ったときは<原点回帰を行います。

Imageオブジェクトを忘れない!

エレメント操作を行う場合に、ついつい$関数で拡張エレメントを利用してしまうのですが、そもそもJavaScriptには画像を扱うための組み込みオブジェクトとしてImageオブジェクトがあります。こいつを利用しない手はありません。つまり、こんなコードになります。超単純なコードですけど。

  Image image = new Image('hoge');
  hoge.src = 'foo.jpg';
  

これだと絶対にIE6でもレンダリングできます!

検証

ついでに検証コードをかいてみました。Imageオブジェクト経由のスワップと$関数を利用したスワップで、いかに露骨に違ってくるか、を確認してみてください。Firefoxだと違いは出ないと思うのでIE6がベストです。

教訓

ブラウザオブジェクトをおろそかにしない!!