Greasy Fork

Greasy Fork is available in English.

平滑滚动翻页

使用上下键或WS键进行平滑滚动翻页,一次翻页0.9倍页面距离。键盘左右键或A/D键模拟点击页面中【上一页|上一章】【下一页|下一章】按钮,双击只点击【上一章】【下一章】按钮。可以与自动滚屏助手脚本联动。

目前为 2025-05-12 提交的版本,查看 最新版本

// ==UserScript==
// @name         平滑滚动翻页
// @namespace    http://tampermonkey.net/
// @version      1.9
// @description  使用上下键或WS键进行平滑滚动翻页,一次翻页0.9倍页面距离。键盘左右键或A/D键模拟点击页面中【上一页|上一章】【下一页|下一章】按钮,双击只点击【上一章】【下一章】按钮。可以与自动滚屏助手脚本联动。
// @author       coccvo
// @include      *
// @exclude      https://www.bilibili.com/*
// @grant        none
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAVdJREFUWEftlj1Ow0AQhd9YWKKmy3b8FPSpiKUojXMaKOAg0HAZCEUktB0HoMDu4twBkwxaLEvG7C7GzMoowvV437dvfnYIA3/k00+TgiX4Flo5df4BfuVABEx5yxuOSPtSFSQFRvxOq0cjPD9bTXwQ4gBN8frmPghRAJv4dxCCAPRCtH325Zs5OgX4pBkjCNBvKuwmAAMZgFvjSQQ6Z/Cxyx9xB8p4FC+X9NYUnM14Ly7XpQ1CFMAmXou6IMQACJTd69GnCm/fOE3WGcBHQbqAgasHrW58vTBPiksGrncTAEC+0MpZ7ebWaVLkAA6DOGAO9RXhePwUH+yr13aKxIqwPtgG4RI3/4gDVCCUE/hjEDFw0bY9WAr6vAaBHOiOIgjwB55j70IyXU1483U/FHSgst26kjnEg3XBoEtpXX6DruXdeyDYIOqOIF6E3aWryN4APxXqE/8OqY/0IehdmXQAAAAASUVORK5CYII=
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 状态变量
    let isScrollKeyPressed = false;
    let autoScrollWasActive = false;
    let lastKeyPressTime = 0;
    const doublePressThreshold = 300; // 双击判定阈值(毫秒)
    let scrollDistance = window.innerHeight * 0.9; // 默认滚动距离

    // 检查自动滚动接口
    const isAutoScrollAvailable = () => typeof window.getAutoScrollState === 'function';

    // 模拟点击函数
    function simulateClickByText(textContent) {
        const links = document.querySelectorAll('a');
        for (let i = 0; i < links.length; i++) {
            if (links[i].textContent.trim() === textContent) {
                links[i].click();
                return true;
            }
        }
        return false;
    }

    // 分页按钮检测
    function hasNextPageButton() {
        return simulateClickByText('下一页') || simulateClickByText('下一页>');
    }

    function hasLastPageButton() {
        return simulateClickByText('上一页') || simulateClickByText('上一页>');
    }

    // 处理单击分页
    function handleSingleClick(direction) {
        const isPrev = direction === 'prev';
        if (isPrev ? hasLastPageButton() : hasNextPageButton()) {
            if (isPrev) {
                simulateClickByText('上一页') || simulateClickByText('<上一页');
            } else {
                simulateClickByText('下一页') || simulateClickByText('下一页>');
            }
        } else {
            simulateClickByText(isPrev ? '上一章' : '下一章');
        }
        document.body.focus();
    }

    // 处理双击分页
    function handleDoubleClick(direction) {
        simulateClickByText(direction === 'prev' ? '上一章' : '下一章');
        document.body.focus();
    }

    // 按键按下事件
    function handleKeyDown(event) {
        const target = event.target;
        if (
            target.tagName.toLowerCase() === 'input' ||
            target.tagName.toLowerCase() === 'textarea' ||
            target.isContentEditable ||
            target.closest('[contenteditable="true"]')
        ) return;

        const key = event.key.toLowerCase();
        const isScrollKey = ['w', 'arrowup', 's', 'arrowdown'].includes(key);

        if (isScrollKey) {
            isScrollKeyPressed = true;
            lastKeyPressTime = performance.now(); // 记录按键时间

            // 暂停自动滚动
            if (isAutoScrollAvailable() && window.getAutoScrollState()) {
                autoScrollWasActive = true;
                window.turnOffAutoScroll();
            }

            // WS键单次滚动
            if (key === 'w' || key === 'arrowup') {
                event.preventDefault();
                window.scrollBy({ top: -scrollDistance, left: 0, behavior: 'smooth' });
            } else if (key === 's' || key === 'arrowdown') {
                event.preventDefault();
                window.scrollBy({ top: scrollDistance, left: 0, behavior: 'smooth' });
            }
        }

        // AD键分页逻辑(保持不变)
        if (key === 'arrowleft' || key === 'a' || key === 'arrowright' || key === 'd') {
            const now = performance.now();
            if (now - lastKeyPressTime < doublePressThreshold) {
                handleDoubleClick(key);
            } else {
                handleSingleClick(key);
            }
            lastKeyPressTime = now;
        }
    }

    // 按键释放事件
    function handleKeyUp(event) {
        const key = event.key.toLowerCase();
        const isScrollKey = ['w', 'arrowup', 's', 'arrowdown'].includes(key);

        if (isScrollKey) {
            isScrollKeyPressed = false;
        }

        // WS键释放后延迟恢复自动滚动
        if (isScrollKey && autoScrollWasActive) {
            setTimeout(() => {
                if (!isScrollKeyPressed && isAutoScrollAvailable()) {
                    window.startAutoScroll();
                    autoScrollWasActive = false;
                }
            }, 500); // 延迟500ms恢复
        }
    }

    // 页面加载初始化
    window.addEventListener('load', () => {
        scrollDistance = window.innerHeight * 0.9; // 动态计算滚动距离
    });

    // 窗口大小变化时更新滚动距离
    window.addEventListener('resize', () => {
        scrollDistance = window.innerHeight * 0.9;
    });

    // 添加事件监听
    document.addEventListener('keydown', handleKeyDown);
    document.addEventListener('keyup', handleKeyUp);
})();