イメージ表示タイミングをコントロールしてみたい
たくさんのIMGタグを作ると、それらの表示に時間がかかることがある。
仕組みを聞いてみると、
・IMGタグを作る(親要素へ追加する)ことと、ブラウザが実際に画像をダウンロードして表示することにはズレがある。
・極端なことをいうと、実際のダウンロード&表示に処理が集中してしまう。
これの解決策のひとつとして、「見えたIMGタグを処理対象にする」ということをしてくれるAPIを使う。
IntersectionObserver API
詳しい内容はここに載っています(個人的には読んでもピンとこないけど)
https://developer.mozilla.org/ja/docs/Web/API/IntersectionObserver
APIを使わない場合のIMGタグ例
普通は、IMGタグの「src」に表示対象のURL(ダウンロード先URL)を指定する
<img class="base" src="<画像URL>" alt="">
これでブラウザがダウンロード&表示してくれる。
APIを使う場合のIMGタグ例
IMGタグを作るとき、「src」に「空」を指定する。
代わりに、(一例です)「data-filename」に画像URLを指定する。
<img class="base" src="" data-filename="<画像URL>" alt="">
「data-filename」というのは、実際には「data-*」という形式で使える便利な属性とのこと。
「data-*」はアプリで「dataset」プロパティを使って自由にデータを定義できる仕組みらしい。
https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/dataset
API の利用イメージ
IntersectionObserverはタグを監視対象にするための機能ということで。
使い方のイメージはこんな感じ。
・どのタグに内包されるタグを対象にしたいか
・監視したいタグを指定する
・監視対象のタグが「見えた」ときにAPIが通知
・監視していたタグが「見えたら」監視対象から外す
監視対象のタグを指定する
まず、インスタンス化
const options: IntersectionObserverInit = {
root: scrollRoot, // このタグを基準にする
rootMargin: "0px", // ギリギリで見えたら反応
threshold: 0.1 // 10%見えたら反応
}
const observer = new IntersectionObserver(callback, options)
「見えた」ときに通知を受ける関数(callback)を用意する
const callback: IntersectionObserverCallback = async (entries) => {
}
※「async」は必要なとき指定します。
監視したいタグを指定する
タグ内のIMGを検索するには「querySelectorAll」を使うと便利。
const images = scrollRoot.querySelectorAll(`img[data-filename]`)
API に「監視」したいタグを知らせる。
images.forEach(img => observer.observe(img))
監視対象のタグが「見えた」ときにAPIが通知
前述の「callback」が呼び出され対象のタグをおしえてくれる。
const callback: IntersectionObserverCallback = async (entries) => {
await entries.forEach( async entry => { //見えたタグ
if (entry.isIntersecting) { //監視中
//画像URLを取り出す
const img = entry.target as HTMLImageElement
const url = img.dataset.filename
//画像をセット(表示)
img.src = url
//監視対象からはずす
observer.unobserve(img)
}
}
}
※「async/await」は必要なとき指定します。
次はキャラ検索
キャラ一覧がスムーズに動くようになると、キャラ名で検索したくなった。
キャラ名でヒットしたキャラへスクロールしたい。