25/5/2025

pannellum.jsをWebPやAVIF対応ブラウザなら自動切替したい

前回360度天球画像をブログに貼る手段をPannellumに変えたことを書きました。

theta360.comの代替はPannellumで決まり!

そしたらちょっと欲が出てきまして。
JPEGじゃなくて、もし閲覧者のブラウザが対応していればより軽量なAVIFやWebPでパノラマ画像を表示させたい!と。

普通は難しい話じゃないですよね?
.htaccessでACCEPTヘッダーがimage/avifに対応していて、かつ当該ファイルが存在するなら.avif画像を表示させるという。WebPも同様。
imgタグの場合は問題なく切り替えてくれます。

ところが、クエリ文字列で拡張子付きのファイル名を指定しなければならないPannellumの場合、.htaccessで画像を自動切り替えすることが出来ません。

それなら、JavaScriptでWebPやAVIF対応ブラウザかどうかを判別して、クエリ文字列の拡張子だけ入れ替えちゃえばいいよね?
で、iframeを出力してくれるようにすれば楽できるんじゃね?と。

JSでWebP対応かどうか判定するには1ピクセルの画像を作ってみるって聞いたことある。
AVIFも同じようにできるのかな?と思って調べたら、
Utiliser les formats AVIF et Webp pour alléger votre site
というフランス語のページにコードがあったので参考にさせていただきました。ありがたや。

そんなわけで書イテミタ。

すいません、ゆるふわ脳なのでシンプルにするためにいくつか制約ががが。

  1. 元画像の拡張子は.jpgのみ。.jpegは未対応なのゴメンなさい
  2. *.webpや*.avifファイルが実際に存在するかどうかは調べてません
  3. hoge.jpgの他にhoge.webpとhoge.avifも同じディレクトリに用意しておく
  4. pannellum.htmファイルと同じディレクトリにこのjsファイルを置く
  5. 出力されるiframeの大きさは別途CSSで設定する

5.がね〜…widthとheightをパラメータとして渡せばいいだけなんですが、クエリ文字列にwidthとかheightが入っているとpannellumが怒るんですよ…😅
追記:widthとheightをパラメータとして渡せるようにしました。
オリジナルのpannellum.htmではwidthに入れた数値のせいでスマホではみ出すので、ここで指定したwidthはmax-width値として渡しています。
ついでにiframeのclassも設定できるようにしました。

使い方はpannellumファイルの代わりにこのpannellum.avif-webp.jsをスクリプトとして貼るだけ。
パラメータはpannellum.jsに使えるものなら同じように書けます。


<script src="/media/pano/pannellum.avif-webp.js#panorama=TEST.jpg&autoLoad=true&autoRotate=-8&width=720&height=450"></script>

で、実際に使ってみました。
実際に読み込まれた画像形式によってJPEG、WebP、AVIFの文字入り画像が出ます。

あれ?

AVIF対応ブラウザでもWebPが表示される!?😅

AVIF判定部分??🤔
試しに自分で1pxのAVIF画像を作ってBase64に変換してみたら12.24KBありました。デカすぎぃ😂

しかも.htaccessの判定もあやしい…😨

360 panorama format test

最初JPEGになったり、スーパーリロードするとAVIFになったりする……ダメじゃん😥

時間切れなので解決したら追記します。🙇‍♂️💦

追記:参考にさせていただいたコードのavif画像のBase64部分を下のように変更したら期待通り動作しました。

const avifData = 'data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A='

追記2:うっかりしてたんですが同一ページ内に複数のパノラマを貼れるように即時関数化しました。