您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Scroll down/up by aligning images
// ==UserScript== // @name Next Image/Previous Image with Alignment and Large Image Support // @author rekt // @license MIT // @namespace http://tampermonkey.net/ // @version 1.0 // @description Scroll down/up by aligning images // @include * // @grant unsafeWindow // ==/UserScript== (function() { const KEY_W = "w"; const KEY_S = "s"; let positions = []; function findNonTruncatedPosition(initialPosition, viewportHeight) { let currentPosition = initialPosition; let found = false; while (!found) { found = true; for (let i = 0; i < positions.length; i++) { const [, imgTop, imgBottom] = positions[i]; if (imgTop < currentPosition && imgBottom > currentPosition) { currentPosition = imgTop; found = false; break; } } } return currentPosition; } function scrollToNextImage(currentScroll, viewportHeight) { const nextScrollPosition = currentScroll + viewportHeight; const currentBottomEdge = currentScroll + viewportHeight; // First check for large images that extend beyond viewport for (let i = 0; i < positions.length; i++) { if (positions[i][1] <= currentScroll && positions[i][2] > currentBottomEdge) { // Large image case: find next image after this one for (let j = i + 1; j < positions.length; j++) { if (positions[j][1] > positions[i][1]) { return findNonTruncatedPosition(positions[j][1], viewportHeight); } } // If no next image found, scroll by viewport height return findNonTruncatedPosition(nextScrollPosition, viewportHeight); } } // Normal case: handle truncated images for (let i = 0; i < positions.length; i++) { if (positions[i][2] > currentBottomEdge && positions[i][1] < nextScrollPosition) { return findNonTruncatedPosition(positions[i][1], viewportHeight); } } return findNonTruncatedPosition(nextScrollPosition, viewportHeight); } function scrollToPreviousImage(currentScroll, viewportHeight) { const previousScrollPosition = currentScroll - viewportHeight; const newTopCandidate = Math.max(0, previousScrollPosition); for (let i = positions.length - 1; i >= 0; i--) { if (positions[i][1] < currentScroll && positions[i][2] > newTopCandidate) { return findNonTruncatedPosition(positions[i][1], viewportHeight); } } return findNonTruncatedPosition(newTopCandidate, viewportHeight); } function scrollShiftUp(currentScroll, viewportHeight) { const prevViewportTop = Math.max(currentScroll - viewportHeight, 0); let newScroll = prevViewportTop; for (let i = positions.length - 1; i >= 0; i--) { const imgTop = positions[i][1]; if (imgTop >= prevViewportTop && imgTop <= prevViewportTop + 20) { newScroll = imgTop; break; } if (imgTop < prevViewportTop && imgTop >= prevViewportTop - 100) { newScroll = imgTop; break; } } return findNonTruncatedPosition(newScroll, viewportHeight); } function getYOffset(node) { let offset = 0; while (node) { offset += node.offsetTop; node = node.offsetParent; } return offset; } document.addEventListener("keydown", function(event) { if (event.ctrlKey || event.altKey) return; const tagName = event.target.tagName; const contentEditable = event.target.getAttribute("contenteditable"); if ((tagName && tagName.match(/input|select|textarea/i)) || contentEditable === "true") { return; } positions = []; const allImages = document.images; for (let idx = 0; idx < allImages.length; idx++) { const img = allImages[idx]; if (img.width * img.height < 80 * 80) continue; const ytop = getYOffset(img); const ybottom = ytop + img.height; positions.push([idx, ytop, ybottom]); } positions.sort((a, b) => a[1] - b[1]); const currentScroll = Math.max(document.documentElement.scrollTop, document.body.scrollTop); const viewportHeight = window.innerHeight; let newScrollPosition = currentScroll; const key = event.key; const lowerKey = key.toLowerCase(); if (lowerKey === KEY_S && !event.shiftKey) { newScrollPosition = scrollToNextImage(currentScroll, viewportHeight); } else if (lowerKey === KEY_W && !event.shiftKey) { newScrollPosition = scrollToPreviousImage(currentScroll, viewportHeight); } else if (lowerKey === KEY_W && event.shiftKey) { newScrollPosition = scrollShiftUp(currentScroll, viewportHeight); } else { return; } if (newScrollPosition !== currentScroll) { event.preventDefault(); document.body.scrollTop = newScrollPosition; document.documentElement.scrollTop = newScrollPosition; } }); })();