// ==UserScript== // @name 查看图片 // @namespace http://tampermonkey.net/ // @version 3.6 // @description 每次打开重新筛选,保持浏览位置;优先大图≥1000×1000,跳过广告;右下角动态按钮,刷新基于页码定位,支持跳转 // @author Cooper // @match *://*/* // ==/UserScript== (function() { 'use strict'; let lastViewedSrc = null; let pendingPageIndex = null; // 用于刷新时指定目标页码(非 null 时优先使用) // 按钮容器 const btnBox = document.createElement("div"); btnBox.style = ` position:fixed; bottom:15%; right:5%; display:flex; flex-direction:column; align-items:center; gap:4px; z-index:1000000001; `; document.body.appendChild(btnBox); // 重载当前页按钮 const reloadCurrentBtn = document.createElement("button"); reloadCurrentBtn.textContent = "↺"; reloadCurrentBtn.title = "刷新并回到当前页码(不改变页码,重载图片)"; reloadCurrentBtn.style = ` width:40px; height:40px; border-radius:20px; border:1px dashed #0d6efd; color:#0d6efd; font-size:18px; padding:3px 3px; background-color:transparent; display:none; `; btnBox.appendChild(reloadCurrentBtn); // 返回上一张并刷新按钮 const refreshPrevBtn = document.createElement("button"); refreshPrevBtn.textContent = "↻"; refreshPrevBtn.title = "返回上一页码并刷新(页码-1)"; refreshPrevBtn.style = ` width:40px; height:40px; border-radius:20px; border:1px dashed #0d6efd; color:#0d6efd; font-size:18px; padding:3px 3px; background-color:transparent; display:none; `; btnBox.appendChild(refreshPrevBtn); // ON 按钮 const flip = document.createElement("button"); flip.textContent = "ON"; flip.style = ` width:40px; height:40px; border-radius:20px; border:1px dashed #0d6efd; color:#0d6efd; font-size:16px; padding:3px 3px; background-color:transparent; `; btnBox.appendChild(flip); // 跳转按钮 const jumpBtn = document.createElement("button"); jumpBtn.textContent = "跳"; jumpBtn.style = ` width:40px; height:40px; border-radius:20px; border:1px dashed #0d6efd; color:#0d6efd; font-size:14px; padding:3px 3px; background-color:transparent; display:none; `; btnBox.appendChild(jumpBtn); let flag = false; const viewerState = { images: null, jump: null, total: 0, _currentIdx: 0 }; // ↺ 重载当前页:记录当前页码 reloadCurrentBtn.addEventListener("click", (e) => { e.stopPropagation(); if (!flag || !viewerState.images || viewerState.images.length === 0) { alert("请先打开图片浏览器 (点击ON)"); return; } pendingPageIndex = viewerState._currentIdx ?? 0; turnOFF(); flag = false; turnON(); flag = true; }); // ↻ 返回上一页并刷新:当前页码-1(最小为0) refreshPrevBtn.addEventListener("click", (e) => { e.stopPropagation(); if (!flag || !viewerState.images || viewerState.images.length === 0) { alert("请先打开图片浏览器 (点击ON)"); return; } const curIdx = viewerState._currentIdx ?? 0; pendingPageIndex = Math.max(0, curIdx - 1); turnOFF(); flag = false; turnON(); flag = true; }); flip.addEventListener("click", (e) => { e.stopPropagation(); if (!flag) { turnON(); } else { turnOFF(); } flag = !flag; toggleExtraButtons(flag); }); jumpBtn.addEventListener("click", (e) => { e.stopPropagation(); if (!viewerState.jump) { alert("请先打开图片浏览器 (点击ON)"); return; } const currentIdx = viewerState._currentIdx ?? 0; const numStr = prompt(`请输入图片序号 (1-${viewerState.total})`, currentIdx + 1); if (numStr === null) return; const num = parseInt(numStr); if (isNaN(num) || num < 1 || num > viewerState.total) { alert(`请输入 1 到 ${viewerState.total} 之间的数字`); return; } viewerState.jump(num - 1); }); function toggleExtraButtons(visible) { reloadCurrentBtn.style.display = visible ? 'block' : 'none'; refreshPrevBtn.style.display = visible ? 'block' : 'none'; jumpBtn.style.display = visible ? 'block' : 'none'; } function turnON() { const overlay = document.createElement("div"); overlay.id = "img-overlay"; overlay.style = ` position:fixed; top:0; left:0; width:100%; height:100%; background-color:rgba(0, 0, 0, 0.8); display:flex; justify-content:center; z-index:999999999; `; document.body.appendChild(overlay); const imgContainer = document.createElement("div"); imgContainer.style = ` position:relative; width:100%; height:100%; max-width:800px; margin:0; display:flex; align-items:center; justify-content:center; `; overlay.appendChild(imgContainer); const currentImg = document.createElement("img"); currentImg.style = ` width:100%; height:100%; object-fit:contain; display:block; `; currentImg.alt = "正在重新筛选并恢复位置…"; currentImg.style.color = 'white'; imgContainer.appendChild(currentImg); const imgElements = Array.from(document.querySelectorAll("img")); const seen = new Set(); const uniqueImgs = []; for (const img of imgElements) { if (img.src && !seen.has(img.src)) { seen.add(img.src); uniqueImgs.push(img); } } const MIN_SIZE = 1000; const checkIsLarge = (img) => new Promise((resolve) => { if (img.complete && img.naturalWidth > 0) { resolve(img.naturalWidth >= MIN_SIZE && img.naturalHeight >= MIN_SIZE); return; } const testImg = new Image(); const timeout = setTimeout(() => { testImg.src = ''; resolve(false); }, 2000); testImg.onload = () => { clearTimeout(timeout); resolve(testImg.naturalWidth >= MIN_SIZE && testImg.naturalHeight >= MIN_SIZE); }; testImg.onerror = () => { clearTimeout(timeout); resolve(false); }; testImg.src = img.src; }); const startQuickFilter = async () => { let firstLargeIndex = -1; for (let i = 0; i < uniqueImgs.length; i++) { const large = await checkIsLarge(uniqueImgs[i]); if (large) { firstLargeIndex = i; break; } } let images = []; if (firstLargeIndex === -1) { images = uniqueImgs.map(img => img.src); } else { images = uniqueImgs.slice(firstLargeIndex).map(img => img.src); } // 决定起始索引:优先 pendingPageIndex,其次 lastViewedSrc 匹配,再默认为 0 let startIndex = 0; if (pendingPageIndex !== null) { // 刷新按钮指定的页码,确保在合法范围 startIndex = Math.min(pendingPageIndex, images.length - 1); startIndex = Math.max(0, startIndex); pendingPageIndex = null; // 用后即清 } else if (lastViewedSrc && images.length > 0) { const foundIdx = images.indexOf(lastViewedSrc); if (foundIdx !== -1) { startIndex = foundIdx; } } document.body.removeChild(overlay); openViewer(images, startIndex); }; startQuickFilter(); } function openViewer(images, startIndex) { const overlay = document.createElement("div"); overlay.id = "img-overlay"; overlay.style = ` position:fixed; top:0; left:0; width:100%; height:100%; background-color:rgba(0, 0, 0, 0.8); display:flex; justify-content:center; z-index:999999999; `; document.body.appendChild(overlay); const imgContainer = document.createElement("div"); imgContainer.style = ` position:relative; width:100%; height:100%; max-width:800px; margin:0; display:flex; align-items:center; justify-content:center; `; overlay.appendChild(imgContainer); const currentImg = document.createElement("img"); currentImg.style = ` width:100%; height:100%; object-fit:contain; display:block; `; imgContainer.appendChild(currentImg); let currentIdx = startIndex; const showCurrentImg = () => { currentImg.src = images[currentIdx]; currentImg.alt = `${currentIdx + 1}/${images.length}`; flip.textContent = currentIdx + 1; viewerState._currentIdx = currentIdx; }; showCurrentImg(); const updateLastSrc = () => { if (images.length > 0 && currentIdx >= 0 && currentIdx < images.length) { lastViewedSrc = images[currentIdx]; } }; updateLastSrc(); viewerState.images = images; viewerState.jump = (index) => { if (index >= 0 && index < images.length) { currentIdx = index; showCurrentImg(); updateLastSrc(); } }; viewerState.total = images.length; viewerState._currentIdx = currentIdx; overlay.addEventListener("click", (e) => { e.stopPropagation(); const screenHeight = window.innerHeight; const clickY = e.clientY; if (clickY < screenHeight / 2) { if (currentIdx > 0) currentIdx--; } else { if (currentIdx < images.length - 1) currentIdx++; } showCurrentImg(); updateLastSrc(); }); } function turnOFF() { const overlay = document.getElementById("img-overlay"); if (overlay) { document.body.removeChild(overlay); flip.textContent = "ON"; viewerState.jump = null; viewerState.total = 0; viewerState._currentIdx = 0; viewerState.images = null; } } })();