Mobile WebTool

手机网页工具:全屏切换、页面缩放

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Mobile WebTool
// @namespace    howardzhangdqs
// @version      1.0.0
// @author       HowardZhangdqs
// @description  手机网页工具:全屏切换、页面缩放
// @license      WTFPL
// @icon         https://vitejs.dev/logo.svg
// @match        *://*/*
// @run-at       document-idle
// ==/UserScript==

(function () {
  'use strict';

  const styles = ":host{all:initial;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.mwt-container{position:fixed;top:8px;left:8px;z-index:2147483647;user-select:none;-webkit-user-select:none;transition:opacity .3s}.mwt-btn{width:38px;height:38px;border-radius:10px;border:none;background:#0000008c;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 2px 8px #0000004d;transition:background .2s,transform .15s;-webkit-tap-highlight-color:transparent;padding:0;line-height:1}.mwt-btn svg{width:20px;height:20px}.mwt-btn:active{background:#000000bf;transform:scale(.92)}.mwt-menu{margin-top:6px;background:#1e1e1eeb;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-radius:10px;padding:4px 0;min-width:120px;box-shadow:0 4px 16px #0006;overflow:hidden;opacity:0;transform:translateY(-8px) scale(.95);transition:opacity .2s,transform .2s;pointer-events:none}.mwt-menu.mwt-open{opacity:1;transform:translateY(0) scale(1);pointer-events:auto}.mwt-zoom-display{padding:6px 14px;text-align:center;font-size:12px;color:#ffffff80;border-bottom:1px solid rgba(255,255,255,.08);font-variant-numeric:tabular-nums}.mwt-menu-item{display:flex;align-items:center;gap:8px;width:100%;padding:9px 14px;border:none;background:none;color:#fff;font-size:14px;cursor:pointer;text-align:left;transition:background .15s;-webkit-tap-highlight-color:transparent;font-family:inherit}.mwt-menu-item:active{background:#ffffff1a}.mwt-menu-item+.mwt-menu-item{border-top:1px solid rgba(255,255,255,.06)}.mwt-menu-icon{width:18px;height:18px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.mwt-menu-icon svg{width:100%;height:100%}";
  const svgTool = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M686-132 444-376q-20 8-40.5 12t-43.5 4q-100 0-170-70t-70-170q0-36 10-68.5t28-61.5l146 146 72-72-146-146q29-18 61.5-28t68.5-10q100 0 170 70t70 170q0 23-4 43.5T584-516l244 242q12 12 12 29t-12 29l-84 84q-12 12-29 12t-29-12Zm29-85 27-27-256-256q18-20 26-46.5t8-53.5q0-60-38.5-104.5T386-758l74 74q12 12 12 28t-12 28L332-500q-12 12-28 12t-28-12l-74-74q9 57 53.5 95.5T360-440q26 0 52-8t47-25l256 256ZM472-488Z"/></svg>';
  const svgFullscreen = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M800-600v-120H680v-80h120q33 0 56.5 23.5T880-720v120h-80Zm-720 0v-120q0-33 23.5-56.5T160-800h120v80H160v120H80Zm600 440v-80h120v-120h80v120q0 33-23.5 56.5T800-160H680Zm-520 0q-33 0-56.5-23.5T80-240v-120h80v120h120v80H160Zm80-160v-320h480v320H240Zm80-80h320v-160H320v160Zm0 0v-160 160Z"/></svg>';
  const svgZoomIn = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Zm-40-60v-80h-80v-80h80v-80h80v80h80v80h-80v80h-80Z"/></svg>';
  const svgZoomOut = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400ZM280-540v-80h200v80H280Z"/></svg>';
  const svgReset = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M440-122q-121-15-200.5-105.5T160-440q0-66 26-126.5T260-672l57 57q-38 34-57.5 79T240-440q0 88 56 155.5T440-202v80Zm80 0v-80q87-16 143.5-83T720-440q0-100-70-170t-170-70h-3l44 44-56 56-140-140 140-140 56 56-44 44h3q134 0 227 93t93 227q0 121-79.5 211.5T520-122Z"/></svg>';
  const ZOOM_STEP = 10;
  const ZOOM_MIN = 30;
  const ZOOM_MAX = 200;
  const AUTO_HIDE_MS = 1e4;
  (() => {
    let currentZoom = 100;
    let menuOpen = false;
    let hideTimer;
    const host = document.createElement("div");
    host.id = "mwt-root";
    document.body.appendChild(host);
    const shadow = host.attachShadow({ mode: "closed" });
    const styleEl = document.createElement("style");
    styleEl.textContent = styles;
    shadow.appendChild(styleEl);
    const container = document.createElement("div");
    container.className = "mwt-container";
    shadow.appendChild(container);
    const btn = document.createElement("button");
    btn.className = "mwt-btn";
    btn.innerHTML = svgTool;
    container.appendChild(btn);
    const menu = document.createElement("div");
    menu.className = "mwt-menu";
    container.appendChild(menu);
    const zoomDisplay = document.createElement("div");
    zoomDisplay.className = "mwt-zoom-display";
    zoomDisplay.textContent = `${currentZoom}%`;
    menu.appendChild(zoomDisplay);
    function createMenuItem(icon, label, onClick) {
      const item = document.createElement("button");
      item.className = "mwt-menu-item";
      item.innerHTML = `<span class="mwt-menu-icon">${icon}</span><span>${label}</span>`;
      item.addEventListener("click", (e) => {
        e.stopPropagation();
        resetHideTimer();
        onClick();
      });
      menu.appendChild(item);
      return item;
    }
    const fullscreenItem = createMenuItem(svgFullscreen, "全屏", toggleFullscreen);
    createMenuItem(svgZoomIn, "放大", zoomIn);
    createMenuItem(svgZoomOut, "缩小", zoomOut);
    createMenuItem(svgReset, "重置缩放", zoomReset);
    function resetHideTimer() {
      clearTimeout(hideTimer);
      hideTimer = setTimeout(() => {
        container.style.opacity = "0";
        container.style.pointerEvents = "none";
        setTimeout(() => host.remove(), 300);
      }, AUTO_HIDE_MS);
    }
    resetHideTimer();
    function updateZoomDisplay() {
      zoomDisplay.textContent = `${currentZoom}%`;
      document.documentElement.style.zoom = `${currentZoom}%`;
    }
    function toggleFullscreen() {
      if (document.fullscreenElement) {
        document.exitFullscreen();
      } else {
        document.documentElement.requestFullscreen();
      }
      toggleMenu();
    }
    function updateFullscreenIcon() {
      fullscreenItem.querySelector(".mwt-menu-icon").innerHTML = svgFullscreen;
    }
    function zoomIn() {
      currentZoom = Math.min(currentZoom + ZOOM_STEP, ZOOM_MAX);
      updateZoomDisplay();
    }
    function zoomOut() {
      currentZoom = Math.max(currentZoom - ZOOM_STEP, ZOOM_MIN);
      updateZoomDisplay();
    }
    function zoomReset() {
      currentZoom = 100;
      updateZoomDisplay();
    }
    function toggleMenu() {
      menuOpen = !menuOpen;
      menu.classList.toggle("mwt-open", menuOpen);
    }
    btn.addEventListener("click", (e) => {
      e.stopPropagation();
      toggleMenu();
      resetHideTimer();
    });
    document.addEventListener("click", () => {
      if (menuOpen) {
        menuOpen = false;
        menu.classList.remove("mwt-open");
      }
    });
    document.addEventListener("fullscreenchange", () => {
      updateFullscreenIcon();
    });
  })();

})();