// ==UserScript== // @name Instant Scroll // @namespace http://tampermonkey.net/ // @version 2.5.1 // @description 在浏览器中添加悬浮翻页按钮,实现瞬时滚动。兼容即刻、小红书等单页面应用(SPA)的内部区域滚动。 // @author chen // @match https://*/* // @grant none // @downloadURL https://update.greasyfork.icu/scripts/569124/Instant%20Scroll.user.js // @updateURL https://update.greasyfork.icu/scripts/569124/Instant%20Scroll.meta.js // ==/UserScript== (function() { 'use strict'; // 避免在非顶层窗口(如 iframe)中加载 if (window.top !== window.self) return; // 创建悬浮容器 const container = document.createElement('div'); container.style.position = 'fixed'; // 最小 60px,首选屏幕高度的 8%,最大不超过 100px container.style.bottom = 'clamp(60px, 8vh, 100px)'; // 最小 10px,首选屏幕宽度的 3%,最大不超过 40px container.style.left = 'clamp(10px, 3vw, 40px)'; container.style.zIndex = '999999'; container.style.display = 'flex'; container.style.flexDirection = 'column'; container.style.gap = 'clamp(10px, 2vmin, 20px)'; // 统一样式函数 function createButton(text) { const btn = document.createElement('button'); btn.innerText = text; // 按钮大小:最小 35px,理想情况屏幕较短边的 8%,最大 60px const size = 'clamp(35px, 8vmin, 60px)'; btn.style.width = size; btn.style.height = size; btn.style.borderRadius = '50%'; btn.style.backgroundColor = 'transparent'; btn.style.color = '#000'; btn.style.border = 'solid #333333'; btn.style.textShadow = ` -1px -1px 0 #ffffff, 1px -1px 0 #ffffff, -1px 1px 0 #ffffff, 1px 1px 0 #ffffff, 0px 1px 0 #ffffff, 0px -1px 0 #ffffff, -1px 0px 0 #ffffff, 1px 0px 0 #ffffff `; // 字体大小:最小 14px,首选 3vmin,最大 22px btn.style.fontSize = 'clamp(14px, 3vmin, 22px)'; // 优化:防止频繁点击时选中文本 btn.style.userSelect = 'none'; btn.style.cursor = 'pointer'; // 关闭移动端触摸时产生的灰色高亮背景(最关键的一步) btn.style.webkitTapHighlightColor = 'transparent'; return btn; } const btnUp = createButton('▲'); const btnDown = createButton('▼'); // === 核心改进逻辑:动态检测并记录当前激活的滚动容器 === let activeScrollContainer = window; // 向上遍历DOM树,寻找具有滚动条的容器 function getScrollContainer(node) { let current = node; while (current && current !== document && current !== document.body && current !== document.documentElement) { // 确保是元素节点 if (current.nodeType === 1) { const style = window.getComputedStyle(current); const overflowY = style.overflowY; const isScrollable = (overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay'); // 判断是否具有可滚动属性,并且内容确实超出了容器高度 if (isScrollable && current.scrollHeight > current.clientHeight) { return current; } } current = current.parentNode; } return window; } // 监听用户的点击或触摸事件,更新目标滚动区域 function updateActiveContainer(e) { // 如果点击的是悬浮按钮自身,则不更新 if (container.contains(e.target)) return; let target = e.target; // 如果点到了文本节点,取它的父元素 if (target.nodeType !== 1) target = target.parentElement; activeScrollContainer = getScrollContainer(target); } // 使用捕获阶段 (true) 监听鼠标点击与平板触摸,确保能第一时间捕捉焦点 document.addEventListener('mousedown', updateActiveContainer, true); document.addEventListener('touchstart', updateActiveContainer, true); // 智能获取要滚动的容器 function getTargetContainer() { // 1. 如果之前记录的容器依然有效且还在 DOM 树中,直接使用 if (activeScrollContainer && activeScrollContainer !== window && document.contains(activeScrollContainer)) { return activeScrollContainer; } // 2. 智能回退:如果没有主动点击页面(刚刷新网页),尝试获取屏幕中心的元素来推测滚动容器 const centerX = window.innerWidth / 2; const centerY = window.innerHeight / 2; const el = document.elementFromPoint(centerX, centerY); if (el) { const centerContainer = getScrollContainer(el); if (centerContainer !== window) { activeScrollContainer = centerContainer; return centerContainer; } } // 3. 默认回退使用 window return window; } // 执行滚动的统一下发函数 function doScroll(direction) { const target = getTargetContainer(); // direction: -1 为向上,1 为向下 const distance = direction * window.innerHeight * 0.85; if (target === window) { window.scrollBy({ top: distance, behavior: 'instant' }); } else { target.scrollBy({ top: distance, behavior: 'instant' }); } } // 绑定 Page Up 滚动逻辑 (向上滚动当前屏幕高度的85%) btnUp.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); doScroll(-1); }); // 绑定 Page Down 滚动逻辑 (向下滚动当前屏幕高度的85%) btnDown.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); doScroll(1); }); // 将按钮添加到页面 container.appendChild(btnUp); container.appendChild(btnDown); document.body.appendChild(container); })();