ページ上に設置した画像をクリックすると拡大してポップアップ表示することができるJavaScriptプラグイン「PhotoSwipe」のバージョン5です。
このブログでは過去に何度か触れているライブラリですが、最初に書いた記事がv4についてでした。現在(2022.10.13)の最新バージョンはv5となっており、コードの記述方法がガラッと変わったので今回改めてメモしておこうと思います。
▼過去記事は下記をご覧ください。
とりあえず動かすために作ったデモはこちら。
コードはGitHubに置いてます。
https://github.com/inos3910/photoswipe-v5-demo
デモと同じようにシンプルにリスト表示された画像に対してPhotoSwipeを設定するための使い方について。
必要なパッケージをインストールします。
$ yarn add photoswipe
パッケージに入っているCSSを読み込みます。
@use 'photoswipe/dist/photoswipe.css';
別に他のCSSとバンドルする必要ないって場合はそのままファイルを読み込ませればOKです。
<link rel="stylesheet" href="photoswipe/dist/photoswipe.css">
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を入れておく。(サムネイルの時と拡大する時で読み込む画像を分けられる。)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
を追加したり、ポップアップ時の拡大するようなアニメーションを使いたくない場合は、showHideAnimationType
をfade
やnone
に変更したりします。
const lightbox = new PhotoSwipeLightbox({
gallery :'#js-gallely,#js-gallery-2',
children : 'a',
pswpModule : PhotoSwipe,
bgOpacity : 0.3,
showHideAnimationType: 'fade'
});
その他のオプション、各種イベントやメソッドについて公式ドキュメントをご確認ください。
それ以外で、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-width
とdata-pswp-height
の属性を手動で設定する必要がなくなりました。
あとはCSSで画像リストをお好きに調整すれば完成!
v4→v5で面倒なコードが全部なくなってスッキリしたので使いやすくなりました。
無駄なjQuery依存もなく、モダンブラウザでしっかり動くし、オプション・イベント豊富で何かと使いやすいです。
また、ReactやVueでも使えるため様々な案件で取り入れやすく、非常におすすめです。