【JS】PhotoSwipe v5を使って画像をポップアップ表示する

【JS】PhotoSwipe v5を使って画像をポップアップ表示する

PhotoSwipe v5とは?

ページ上に設置した画像をクリックすると拡大してポップアップ表示することができるJavaScriptプラグイン「PhotoSwipe」のバージョン5です。

このブログでは過去に何度か触れているライブラリですが、最初に書いた記事がv4についてでした。現在(2022.10.13)の最新バージョンはv5となっており、コードの記述方法がガラッと変わったので今回改めてメモしておこうと思います。

▼過去記事は下記をご覧ください。

PhotoSwipe v5のデモ

とりあえず動かすために作ったデモはこちら。

PhotoSwipe v5 のデモ

コードはGitHubに置いてます。

https://github.com/inos3910/photoswipe-v5-demo

PhotoSwipe v5の使い方

デモと同じようにシンプルにリスト表示された画像に対してPhotoSwipeを設定するための使い方について。

インストール

必要なパッケージをインストールします。

$ yarn add photoswipe

CSS(Sass)

パッケージに入っているCSSを読み込みます。

@use 'photoswipe/dist/photoswipe.css';

別に他のCSSとバンドルする必要ないって場合はそのままファイルを読み込ませればOKです。

<link rel="stylesheet" href="photoswipe/dist/photoswipe.css">

HTML

htmlはv4の時とほとんど同じでOKです。

<div class="c-grid" id="js-gallery">
  <a href="./assets/images/sample-1.jpg" class="c-grid__item is-loading" target="_blank" rel="noopener">
    <img src="./assets/images/sample-1.jpg" width="1080" height="1080" alt="" loading="lazy">
  </a>
  <a href="./assets/images/sample-2.jpg" class="c-grid__item is-loading" target="_blank" rel="noopener">
    <img src="./assets/images/sample-2.jpg" width="1080" height="1080" alt="" loading="lazy">
  </a>
  <a href="./assets/images/sample-3.jpg" class="c-grid__item is-loading" target="_blank" rel="noopener">
    <img src="./assets/images/sample-3.jpg" width="1080" height="1080" alt="" loading="lazy">
  </a>
  <a href="./assets/images/sample-4.jpg" class="c-grid__item is-loading" target="_blank" rel="noopener">
    <img src="./assets/images/sample-4.jpg" width="1080" height="1080" alt="" loading="lazy">
  </a>
  <a href="./assets/images/sample-5.jpg" class="c-grid__item is-loading" target="_blank" rel="noopener">
    <img src="./assets/images/sample-5.jpg" width="1080" height="1080" alt="" loading="lazy">
  </a>
  <a href="./assets/images/sample-6.jpg" class="c-grid__item is-loading" target="_blank" rel="noopener">
    <img src="./assets/images/sample-6.jpg" width="1080" height="1080" alt="" loading="lazy">
  </a>
</div>
<!-- /.c-grid -->
  • 画像のリストを囲む要素(ここでは.c-grid)に、あとでJSで使うために特定のidやclassなどを振っておく。ここではidにjs-galleryと指定。
  • 各アイテム(ここでは.c-grid__item)に、.is-loading(画像の読み込み用のクラス)を付けておく。.is-loadingにはCSSでpointer-events:none;を指定しておき、読み込み中はクリックさせない。
  • 画像の枚数は自由。
  • imgタグはaタグで囲み、href属性にポップアップ時に表示したい画像のURLを入れておく。(サムネイルの時と拡大する時で読み込む画像を分けられる。)

JS

v4→v5で大きく変わったのがJSのコードです。

import PhotoSwipeLightbox from 'photoswipe/lightbox';
import PhotoSwipe from 'photoswipe';

class Gallery {
  constructor() {
    this.imagePopUp();
  }

  //特定の画像の読み込み
  loadImage(src) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => resolve(img);
      img.onerror = (e) => reject(e);
      img.src = src;
    });
  }

  // スライド画像のポップアップ(PhotoSwipe)
  imagePopUp(){
    const gallery = document.querySelector('#js-gallery');
    if(!gallery){
      return;
    }
    
    // aタグにdata-pswp-widthとdata-pswp-height属性を付ける
    const galleries = gallery.querySelectorAll('a');
    galleries.forEach((el, index, array) => {
      this.loadImage(el.href).then( img => {
        el.setAttribute('data-pswp-width', img.naturalWidth);
        el.setAttribute('data-pswp-height', img.naturalHeight);
        el.classList.remove('is-loading');
      });
    });
    
    // PhotoSwipeを適用
    const lightbox = new PhotoSwipeLightbox({
      gallery              : gallery, //リストを囲む要素を指定
      children             : 'a', //ポップアップさせる要素を指定
      pswpModule           : PhotoSwipe  // PhotoSwipeのCoreモジュールをここに指定
    });

    lightbox.init();
  }
}

new Gallery();

v4の時はポップアップ表示用のHTMLを挿入するための関数を用意したり、画像のリスト情報を配列にして保持したり、細かい設定を書かないと想定した動きにならなかったのですが、v5からはそれらの設定がデフォルトで含まれるようになったためかなり簡潔なコードになりました。

何かカスタマイズしたい時も、APIとしてオプションイベントメソッドがしっかり整理され用意されている状態になったのでv4よりもいろいろとできそうです。

基本的には下記のコードがPhotoSwipeで必要なコードです。

const lightbox = new PhotoSwipeLightbox({
  gallery              : gallery, //リストを囲む要素を指定
  children             : 'a', //ポップアップさせる要素を指定
  pswpModule           : PhotoSwipe // PhotoSwipeのCoreモジュールをここに指定
});

galleryはここでは取得したElementオブジェクトを指定していますが、id、classなどのCSSセレクタでも指定できます。カンマつなぎで複数指定も可能です。

const lightbox = new PhotoSwipeLightbox({
  gallery              :'#js-gallely,#js-gallery-2',
  children             : 'a',
  pswpModule           : PhotoSwipe
});

オプションもけっこうあります。僕は基本ノーマルで使いますが、背景の透過を変更したい時はbgOpacityを追加したり、ポップアップ時の拡大するようなアニメーションを使いたくない場合は、showHideAnimationTypefadenoneに変更したりします。

const lightbox = new PhotoSwipeLightbox({
  gallery              :'#js-gallely,#js-gallery-2',
  children             : 'a',
  pswpModule           : PhotoSwipe,
  bgOpacity            : 0.3,
  showHideAnimationType: 'fade'
});

その他のオプション、各種イベントやメソッドについて公式ドキュメントをご確認ください。

PhotoSwipe公式ドキュメント

それ以外で、v5で実装する際にポイントとなるのが「ポップアップ時の画像のサイズ指定」が必須になっていることです。

ポップアップ時の画像のサイズ指定が必須

v4の時はaタグのdata-size属性にポップアップ時の画像のサイズ指定が必要でしたが、v5ではdata-pswp-width属性とdata-pswp-height属性に画像サイズを指定しておくことが必須になりました。

HTMLに書き込むと下記のような感じ。

<a href="./assets/images/sample-1.jpg" class="c-grid__item" target="_blank" rel="noopener" data-pswp-width="1080" data-pswp-height="1080">
  <img src="./assets/images/sample-1.jpg" width="1080" height="1080" alt="" loading="lazy">
</a>

これを全部に書き込むとなったら、画像のサイズがバラバラだった場合に手間なので、できれば自動化したいですよね。

それが先のコード内でも書いたこちらのコード。

// aタグにdata-pswp-widthとdata-pswp-height属性を付ける
const galleries = gallery.querySelectorAll('a');
galleries.forEach((el, index, array) => {
  this.loadImage(el.href).then( img => {
    el.setAttribute('data-pswp-width', img.naturalWidth);
    el.setAttribute('data-pswp-height', img.naturalHeight);
    el.classList.remove('is-loading');
  });
});

aタグのhref属性に指定した画像URLからwidthとheightを取得して、data-pswp-width属性とdata-pswp-height属性として設定します。属性を設定できたら.is-loadingクラスを削除します。

画像の読み込みは、Promiseを使った簡易な関数を使っています。

loadImage(src) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.onerror = (e) => reject(e);
    img.src = src;
  });
}

async/awaitで書いたらこんな感じ。

const galleries = gallery.querySelectorAll('a');
galleries.forEach( async (el, index, array) => {
  const img = await this.loadImage(el.href);
  el.setAttribute('data-pswp-width', img.naturalWidth);
  el.setAttribute('data-pswp-height', img.naturalHeight);
  el.classList.remove('is-loading');
});

これでポップアップ時の画像サイズを自動で属性を追加できるようになったので、data-pswp-widthdata-pswp-heightの属性を手動で設定する必要がなくなりました。

あとはCSSで画像リストをお好きに調整すれば完成!

PhotoSwipe v5 のデモ

さいごに

v4→v5で面倒なコードが全部なくなってスッキリしたので使いやすくなりました。

無駄なjQuery依存もなく、モダンブラウザでしっかり動くし、オプション・イベント豊富で何かと使いやすいです。

また、ReactやVueでも使えるため様々な案件で取り入れやすく、非常におすすめです。