Universal Auto Scroll

Hands-free reading! Press Alt+Down (or Alt+X) to start/increase speed, Alt+Up to decrease speed, and Escape/Space/Enter to stop scrolling. Manual scrolling is now allowed.

目前为 2025-02-16 提交的版本。查看 最新版本

// ==UserScript==
// @name           Universal Auto Scroll
// @version        1.0
// @namespace      MedX-AA
// @author         MedX
// @license        MIT
// @description    Hands-free reading! Press Alt+Down (or Alt+X) to start/increase speed, Alt+Up to decrease speed, and Escape/Space/Enter to stop scrolling. Manual scrolling is now allowed.
// @icon           data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAABGUlEQVR4nO3VsS4EURQG4E9oRCEh0ZDQi3gDjV7lHXTeAYVo9gl0ahregEapoKEh0SFRbVbIyiSjEYnd2TtzZ5PzJSeZYjbzn/2LQwghlSN8oP/PFO8caqHeAOF/pni3dfpDTuvEArlFA7lFA7lFA7lFA7lFA7lFA7lFA7lFA7m1uoE9dCuErDrd8pvJvDYYvl/OS8oFOhkW6KRcYBKnDYY/x5TEpnHZQPhrzKjJLG5qDH+LOTVbxGMN4Z+xrCGreEsY/h3rGraR6Db0sCmTLXyOEP4L2zLbGWGBXS1xUCH8vhaZwPEQ4U/K37RKca3PBgh/UceVTXmtr3Jd2VTmcfdH+HssGBNLePp1ZVeMmTU8lP988RxCkN43yek7CExEuggAAAAASUVORK5CYII=
// @grant          none
// @include        *
// ==/UserScript==


// === CONFIGURATION ===
const INITIAL_SPEED = 30; // Starting speed in pixels per second
const MAX_FPS = 60; // Prevents excessive CPU usage
const RESET_THRESHOLD = 10; // Sensitivity for manual scroll detection

// === KEY BINDINGS ===
const SPEED_UP_KEYS = new Set([40, 88]); // Alt+Down OR Alt+X
const SPEED_DOWN_KEY = 38; // Alt+Up
const STOP_KEYS = new Set([27, 32, 13]); // Escape, Space, Enter

// === STATE VARIABLES ===
let isScrolling = false, scrollSpeed = 0, lastUpdateTime, realX, realY, hudTimeout;
const scrollElement = document.scrollingElement || document.documentElement;

// === INITIALIZE HUD (Speed Display) ===
const hud = Object.assign(document.createElement("div"), {
    style: `position:fixed; bottom:10px; right:10px; padding:5px 10px; background:rgba(0,0,0,0.7);
            color:#fff; font-size:14px; font-family:Arial; border-radius:5px; z-index:9999; display:none`
});
document.body.appendChild(hud);

// === EVENT LISTENER: Starts scrolling when Alt+Down OR Alt+X is pressed ===
window.addEventListener('keydown', (e) => {
    if (!isScrolling && e.altKey && SPEED_UP_KEYS.has(e.keyCode)) {
        changeSpeed(1.1);
        e.preventDefault();
    }
}, true);

// === EVENT LISTENER: Adjust Speed or Stop Scrolling (only active when scrolling) ===
function handleKeydown(e) {
    if (e.altKey && SPEED_UP_KEYS.has(e.keyCode)) changeSpeed(1.1); // Increase speed
    else if (e.altKey && e.keyCode === SPEED_DOWN_KEY) changeSpeed(0.9); // Decrease speed
    else if (STOP_KEYS.has(e.keyCode)) {
        stopScrolling();
        if (e.keyCode === 32) e.preventDefault(); // Prevent spacebar from triggering unwanted scroll
    }
    if (e.altKey || STOP_KEYS.has(e.keyCode)) e.preventDefault();
}

// === UPDATE SCROLL POSITION WHEN MANUALLY SCROLLING ===
function updateScrollPosition() {
    realX = scrollElement.scrollLeft;
    realY = scrollElement.scrollTop;
}

// === CHANGE SCROLL SPEED ===
function changeSpeed(multiplier) {
    scrollSpeed = Math.max(5, (scrollSpeed || INITIAL_SPEED) * multiplier); // Ensures speed never drops too low
    if (!isScrolling) startScrolling();

    // HUD Update: Uses requestIdleCallback to avoid slowing down scrolling performance
    requestIdleCallback(() => {
        hud.textContent = `Speed: ${scrollSpeed.toFixed(1)} px/s`;
        hud.style.display = "block";
        if (hudTimeout) clearTimeout(hudTimeout);
        hudTimeout = setTimeout(() => (hud.style.display = "none"), 2000);
    });
}

// === START AUTO-SCROLLING ===
function startScrolling() {
    isScrolling = true;
    updateScrollPosition(); // Capture the current position
    lastUpdateTime = performance.now();

    window.addEventListener('keydown', handleKeydown, true); // Activate speed/stop controls
    window.addEventListener('scroll', updateScrollPosition, { passive: true }); // Detect manual scrolling

    requestAnimationFrame(scrollLoop);
}

// === STOP AUTO-SCROLLING ===
function stopScrolling() {
    isScrolling = false;
    scrollSpeed = 0;
    hud.style.display = "none";

    window.removeEventListener('keydown', handleKeydown, true);
    window.removeEventListener('scroll', updateScrollPosition, { passive: true });
}

// === MAIN SCROLL LOOP (EXECUTES AT MAX FPS) ===
function scrollLoop(timestamp) {
    if (!isScrolling) return;

    let elapsed = timestamp - lastUpdateTime;
    realY += (scrollSpeed * elapsed) / 1000; // Adjust position based on time elapsed
    scrollElement.scrollTo(realX, Math.floor(realY));
    lastUpdateTime = timestamp;

    requestAnimationFrame(scrollLoop);
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址