手机网页工具:全屏切换、页面缩放
// ==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();
});
})();
})();