Mobile WebTool

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

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==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();
    });
  })();

})();