0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AstroでViewer.jsを使う

Posted at

SSGのAstroでつくったサイトに画像ビューワーのViewer.jsを設置したお話です。

前提として、画像はpublicフォルダに置き、frontmatterに画像のパス一覧を書きます。
画像が増えたら、随時frontmatterに追記します。
画像一覧を自動でさらって表示する方法があるのかもしれませんが、俺は知らないので泥臭くやります。(ファイル一覧をJSの動くフロントエンドでさらうことはできないと思っているけど、正しいかはわからない)

npm install viewerjsはしておきます。

さて、まずは最終的なコードを提示します。

最終的なコード

photo.astro---
const paintings = [
  {
    text: "かわいい ねこ",
    list: [
      "/assets/paint/cats/pakutaso/1 (1).jpg",
      "/assets/paint/cats/pakutaso/1 (2).jpg",
      "/assets/paint/cats/pakutaso/1 (3).jpg",
    ],
  },
  {
    text: "かわいい いぬ",
    list: [
      "/assets/paint/dogs/pakutaso/1 (1).jpg",
      "/assets/paint/dogs/pakutaso/1 (2).jpg",
      "/assets/paint/dogs/pakutaso/1 (3).jpg",
    ],
  },
  {
    text: "かわいい はな",
    list: [
      "/assets/paint/flowers/pakutaso/1 (1).jpg",
      "/assets/paint/flowers/pakutaso/1 (2).jpg",
      "/assets/paint/flowers/pakutaso/1 (3).jpg",
    ],
  },
];
---

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>

    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.css"
      integrity="sha512-zdX1vpRJc7+VHCUJcExqoI7yuYbSFAbSWxscAoLF0KoUPvMSAK09BaOZ47UFdP4ABSXpevKfcD0MTVxvh0jLHQ=="
      crossorigin="anonymous"
      referrerpolicy9="no-referrer"
    />
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.js"
      integrity="sha512-f8kZwYACKF8unHuRV7j/5ILZfflRncxHp1f6y/PKuuRpCVgpORNZMne1jrghNzTVlXabUXIg1iJ5PvhuAaau6Q=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    ></script>
  </head>
  <body>
    <div id="gallery">
      <div>
        {
          paintings.map((group, index) => (
            <div class="clickListElement">
              <img src={import.meta.env.BASE_URL + group.list[0]} />
              <p>{group.text}</p>
            </div>
          ))
        }
      </div>
      <div>
        {
          paintings.map((group, index) => (
            <ul style="display:none;" id={"image-" + index}>
              {group.list.map((el) => (
                <li>
                  <img src={import.meta.env.BASE_URL + el} />
                </li>
              ))}
            </ul>
          ))
        }
      </div>
    </div>

    <script>
      import Viewer from "viewerjs";

      Array.from(document.querySelectorAll(".clickListElement")).map(
        (el, index) => {
          const el2 = document.getElementById("image-" + index);
          if (el2) {
            const viewer: Viewer = new Viewer(el2);
            el.addEventListener("click", () => {
              viewer.show();
            });
          }
        }
      );
    </script>
  </body>
</html>

最終的な表示

image.png

写真をクリックすると、モーダルで表示されます。

image.png

メモ

リソース

Viewer.jsのCSSとJavaScriptファイルを読み込みます。

    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.css"
      integrity="sha512-zdX1vpRJc7+VHCUJcExqoI7yuYbSFAbSWxscAoLF0KoUPvMSAK09BaOZ47UFdP4ABSXpevKfcD0MTVxvh0jLHQ=="
      crossorigin="anonymous"
      referrerpolicy9="no-referrer"
    />
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.js"
      integrity="sha512-f8kZwYACKF8unHuRV7j/5ILZfflRncxHp1f6y/PKuuRpCVgpORNZMne1jrghNzTVlXabUXIg1iJ5PvhuAaau6Q=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    ></script>

画像データリスト

{ text: "タイトル", list: [パス1, パス2, ...] }というオブジェクトの配列を持ちます。
必要に応じて、これらを追加すると、複数のギャラリーを表示することができます。

const paintings = [
  {
    text: "かわいい ねこ",
    list: [
      "/assets/paint/cats/pakutaso/1 (1).jpg",
      "/assets/paint/cats/pakutaso/1 (2).jpg",
      "/assets/paint/cats/pakutaso/1 (3).jpg",
    ],
  },
  {
    text: "かわいい いぬ",
    list: [
      "/assets/paint/dogs/pakutaso/1 (1).jpg",
      "/assets/paint/dogs/pakutaso/1 (2).jpg",
      "/assets/paint/dogs/pakutaso/1 (3).jpg",
    ],
  },

クリック用の画像表示

ビューワーを開くためのクリック用の画像を表示します。
画像のパスはastro.config.mjsで設定したbaseオプションを参照して、適切に画像表示されるようにしました。

  <div>
    {
      paintings.map((group) => (
        <div class="clickListElement">
          <img src={import.meta.env.BASE_URL + group.list[0]} />
          <p>{group.text}</p>
        </div>
      ))
    }
  </div>

ビューワー用の画像リスト表示(ただし、非表示設定)

ビューワーで表示する画像のリストを出力します。
ただし、画像自体はビューワーで表示され、リスト自体は表示される必要がないので、display:none;しておきます。

また、ビューワーとクリック用の画像を関連させるため、idとしてimage-{index}を設定します。

画像パスは前述と一緒です

  <div>
    {
      paintings.map((group, index) => (
        <ul style="display:none;" id={"image-" + index}>
          {group.list.map((el) => (
            <li>
              <img src={import.meta.env.BASE_URL + el} />
            </li>
          ))}
        </ul>
      ))
    }
  </div>

Viewer.jsの適用

肝心のViewer.jsを適用します。

クリック用の画像(.clickListElement)をすべて取得し、index番号で対応する画像リストを選択、それにViewerを適用します。

さらに、クリック用の画像(.clickListElement)にonclickを設定し、Viewer.jsのshowファンクションを実行します。

import Viewer from "viewerjs";

Array.from(document.querySelectorAll(".clickListElement")).map(
(el, index) => {
  const el2 = document.getElementById("image-" + index);
  if (el2) {
    const viewer: Viewer = new Viewer(el2);
    el.addEventListener("click", () => {
      viewer.show();
    });
  }
}
);

悩んだところ

frontmatterで提議しているpaintings変数にscriptタグ内からアクセスできないので、少しつまずきました。

結論として、querySelectorAllなどで出力済みのHTML要素から必要なデータを読みとることで解決しました。

Thanks

ぱくたそ様から画像を借用しました。
https://www.pakutaso.com/

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?