GM_Gallery

图片列表转换为画廊

このスクリプトは単体で利用できません。右のようなメタデータを含むスクリプトから、ライブラリとして読み込まれます: // @require https://update.sleazyfork.org/scripts/545309/1770977/GM_Gallery.js

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
(function () {
  function addStyle(style) {
    const $style = document.createElement("style");
    document.head.appendChild($style);
    $style.innerHTML = style;
  }

  class GM_Gallery {
    #storageKey = "gallery_mode";
    #gallery_mode = false;
    #srcList;

    constructor({ parser }) {
      this.#gallery_mode = localStorage.getItem(this.#storageKey) === "on";

      if (this.#gallery_mode) {
        this.#srcList = parser();
        this.#initHead();
        this.#initBody();
        this.#initProgress();
        this.#initPreview();
        this.#initStyle();
      }

      this.#initSwitch();
    }

    #initHead() {
      // head只保留title,保存页面时不会下载一堆乱七八糟的css和js
      document.head.innerHTML = `<title>${document.title}</title>`;
    }

    #initBody() {
      document.body.innerHTML = `
        <div id="gallery">
          ${this.#srcList
            .map((src, index) => {
              return `
                <span class="item" data-index="${index}">
                  <img src="${src}" onload="window.onImgLoaded()">
                  <div style="text-align: center;">${index + 1}</div>
                </span>
              `;
            })
            .join("")}
        </div>
        <div id="progress">0/${this.#srcList.length}</div>
      `;

      document.documentElement.scrollTop = 0;
    }

    #initProgress() {
      const $progress = document.querySelector("#progress");
      let loaded = 0;

      document.querySelectorAll("#gallery img").forEach(($img) => {
        $img.onload = () => {
          $progress.innerHTML = `${++loaded} / ${this.#srcList.length}`;
        };
      });
    }

    #initPreview() {
      const preview = new window.GM_Preview({
        showThumbs: false,
        onShow() {
          document.documentElement.classList.add("is-preview");
        },
        onClose() {
          document.documentElement.classList.remove("is-preview");
        },
      });

      document.querySelector("#gallery").onclick = (e) => {
        if (e.target.dataset.index) {
          const index = parseInt(e.target.dataset.index);
          preview.show(this.#srcList, index);
        }
      };
    }

    #initSwitch() {
      const $switch = document.createElement("div");
      document.body.appendChild($switch);
      $switch.textContent = `画廊模式:${this.#gallery_mode ? "开" : "关"}`;
      $switch.id = `gallery_mode_switch`;
      $switch.onclick = () => {
        if (this.#gallery_mode) localStorage.removeItem(this.#storageKey);
        else localStorage.setItem(this.#storageKey, "on");
        location.reload();
      };

      addStyle(`
        #gallery_mode_switch {
          z-index: 1000;
          position: fixed;
          right: 10px;
          top: 10px;
          border-radius: 4px;
          padding: 4px 8px;
          cursor: pointer;
          background-color: rgba(0, 0, 0, 0.8);
          color: #fff;
          font-size: 16px;
          user-select: none;
          opacity: 0.5;
          transition: all 0.3s;

          &:hover {
            opacity: 1;
          }
        }
      `);
    }

    #initStyle() {
      addStyle(`
        * {
          user-select: none;
          -webkit-user-drag: none;
        }

        #gallery {
          display: flex;
          flex-flow: row wrap;
          gap: 10px;
          padding: 50px 0;

          & .item {
            align-self: flex-end;
            cursor: pointer;

            & * {
              pointer-events: none;
            }

            & img {
              width: 100px;
              min-width: 100px;
              min-height: 100px;
              object-fit: contain;
              background-color: #ccc;
              transition: all 0.1s;
              border: 0.5px solid #ccc;
            }

            &:hover img {
              opacity: 0.5;
            }
          }
        }

        #progress {
          position: fixed;
          left: 10px;
          bottom: 10px;
          background-color: rgba(0, 0, 0, 0.8);
          color: #fff;
          border-radius: 4px;
          padding: 4px 8px;
          font-size: 16px;
          opacity: 0.5;
          pointer-events: none;
        }

        html.is-preview {
          overflow: hidden;

          & :is(#progress, #gallery_mode_switch) {
            display: none;
          }
        }
      `);
    }
  }

  window.GM_Gallery = GM_Gallery;
})();