您需要先安装一个扩展,例如 篡改猴、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;
- }
- });
- })();