平滑滚动翻页

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

// ==UserScript==
// @name         平滑滚动翻页
// @namespace    http://tampermonkey.net/
// @version      2.0
// @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;
    let clickTimer = null;
    let scrollDistance = window.innerHeight * 0.9; // 默认滚动距离

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

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

    // 模拟点击函数
    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 handlePageNavigation(direction) {
        if (clickTimer == null) {
            clickTimer = setTimeout(() => {
                const isPrev = direction === 'prev';
                if (isPrev ? hasLastPageButton() : hasNextPageButton()) {
                    if (isPrev) {
                        simulateClickByText('上一页') || simulateClickByText('<上一页');
                    } else {
                        simulateClickByText('下一页') || simulateClickByText('下一页>');
                    }
                } else {
                    simulateClickByText(isPrev ? '上一章' : '下一章');
                }
                document.body.focus();
                clickTimer = null;
            }, 300);
        } else {
            clearTimeout(clickTimer);
            clickTimer = null;
            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;

            // 暂停自动滚动
            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' });
            }
        }
    }

    // 按键释放事件
    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);
})();