画像読み込みでDOM操作が阻害された時に試すこと

公開:2021/02/18
更新:2021/02/18
1 min読了の目安(約1300字TECH技術記事

課題

  • 要素の大きさを他のDOM要素の大きさによって変えたり、ページハッシュでスクロールさせたりする時に、要素のサイズが取れてなくて意図通りに挙動にならないことが多々ある
  • scrollTopを使ってページ全体をスクロールさせる時とか、offsetHeightとかで高さ取得して何かしらの処理をやる時とか、そういう時です
  • そういう時、画像を埋め込んでいる箇所で画像の読み込みに時間がかかり、それによってDOMのサイズが確定する前にDOM操作の処理をしようとしてしまうことが原因なことが多かったです
  • そういう問題に直面した時、自分が解決したいろいろな手法を紹介します

解決手法

setTimeoutを使う

  • scrollHeightやoffsetHeightを使う関数を定義するところで、setTimeoutを挟むという力技です
  • setTimeoutをすることで処理を後回しにできるので、要素の幅が取得できることもあります
  • ただしこれは力技ではあり、どれくらい待てば画像が撮れるのか不明瞭なので、あまり使いたくはないです

img要素にwidth属性、height属性をつける

  • img要素にwidth属性とheight属性をセットしておくことで、その分のスペースを確保してくれます
  • 画像描画前に要素のエリアを確保してくれているので、予期せぬ動きをすることが減ります
  • これはSEO対策的にも有効とのことです
  • 画像を全部表示する場合はimg要素のnaturalHeightやnaturalWidthを渡してみちゃったりします

img.onloadのコールバックに処理を書く

  • var img = document.getElementByID('image')みたいにしてimg要素の画像が読み込み終わってから、その要素のloadイベントにしたい処理を入れます
  • これは画像が読み込まれたタイミングになるので、画像要素の幅だけが問題なのであればこれで解決します

window.requestAnimationFrameのコールバックに処理を書く

  • window.requestAnimationFrameの存在をつい最近知ったのですが、こいつはアニメーションさせたいことを伝えて、フレーム更新の直後にコールバック処理をしてくれるみたいです
  • 一度描画後に呼び出されるので、要素の幅が取れた状態になっているみたいです
  • わかったようであまりわかっていないですが・・・

画像を圧縮する

  • そもそも画像ファイルのサイズが大きいのが問題になっている場合、画像サイズを圧縮する方法も検討するべきだと思います
  • 画像サイズを下げるだけでパフォーマンスも上がると思われます。

まとめ

  • パフォーマンスの麺を考えるとまず画像を圧縮するという選択をして、width属性height属性をつけ、その上で何かしらのコールバックにするのが良いのかなと思います
  • 何か他に良い方法があればお教えいただけると幸いです