📕无动画全屏翻页丨墨水屏一键翻页丨保留比例翻页丨自定义比例

👍忽略滑动动画,快速切换页面,可以通过键盘或浮动窗口进行操作,并调整黑色模式、悬浮窗大小和滑动保留页面比例。

目前為 2024-05-29 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         📕无动画全屏翻页丨墨水屏一键翻页丨保留比例翻页丨自定义比例
// @version      2.3.3
// @description  👍忽略滑动动画,快速切换页面,可以通过键盘或浮动窗口进行操作,并调整黑色模式、悬浮窗大小和滑动保留页面比例。
// @author       Jingyu0123
// @match        *://*/*
// @license GPL
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @namespace https://greasyfork.org/users/1292046
// ==/UserScript==

(function () {
    'use strict';

    // 默认配置变量
    const autoDetectModeOptions = ['关闭', '同色', '反色'];
    var usePgUpPgDn = GM_getValue('usePgUpPgDn', true);
    var reservedHeightPercentage = GM_getValue('reservedHeightPercentage', 0);
    var isBlackMode = GM_getValue('isBlackMode', false);
    var floatWindowSize = GM_getValue('floatWindowSize', 80);
    var autoDetectMode = GM_getValue('autoDetectMode', '关闭');
    var isVerticalLayout = GM_getValue('isVerticalLayout', true);
    var windowOpacity = GM_getValue('windowOpacity', 0.8);
    var textOpacity = GM_getValue('textOpacity', 1.0);
    var floatWindowVisible = GM_getValue('floatWindowVisible', true);
    var upKey = GM_getValue('upKey', 'PageUp');
    var downKey = GM_getValue('downKey', 'PageDown');
    var enableHotkeys = GM_getValue('enableHotkeys', true);

    // 自动检测黑色模式
    function detectDarkMode() {
        const bgColor = window.getComputedStyle(document.body).backgroundColor;
        const colorValues = bgColor.match(/\d+/g);
        if (colorValues) {
            const r = parseInt(colorValues[0]);
            const g = parseInt(colorValues[1]);
            const b = parseInt(colorValues[2]);
            const brightness = (r * 299 + g * 587 + b * 114) / 1000;
            return brightness < 128;
        }
        return false;
    }

    if (autoDetectMode === '同色') {
        isBlackMode = detectDarkMode();
    } else if (autoDetectMode === '反色') {
        isBlackMode = !detectDarkMode();
    }

    // 创建悬浮窗
    function createFloatingWindow() {
    // 检查是否已经存在浮窗
    if (document.getElementById('floatingWindow')) {
        return; // 如果已经存在浮窗,则不创建新的浮窗
    }

    if (!floatWindowVisible) return;

    const floatWindow = document.createElement('div');
    floatWindow.id = 'floatingWindow'; // 为浮窗设置一个唯一的ID
    const initialLeft = GM_getValue('floatWindowLeft', 'calc(100% - 90px)');
    const initialTop = GM_getValue('floatWindowTop', 'calc(100% - 270px)');
    floatWindow.style = `
        position: fixed;
        left: ${initialLeft};
        top: ${initialTop};
        width: ${isVerticalLayout ? floatWindowSize + 'px' : (floatWindowSize * 3) + 'px'};
        height: ${isVerticalLayout ? (floatWindowSize * 3) + 'px' : floatWindowSize + 'px'};
        background-color: ${isBlackMode ? 'black' : 'white'};
        color: ${isBlackMode ? 'white' : 'black'};
        border: 1px solid #ccc;
        z-index: 10000;
        display: flex;
        flex-direction: ${isVerticalLayout ? 'column' : 'row'};
        align-items: center;
        justify-content: space-around;
        cursor: move;
        padding: 5px;
        border-radius: 5px;
        opacity: ${windowOpacity};
    `;
    floatWindow.draggable = true;

    const btnSettings = document.createElement('button');
    btnSettings.innerHTML = '=';
    btnSettings.style = buttonStyle();
    btnSettings.onclick = showSettings;

    const btnDown = document.createElement('button');
    btnDown.innerHTML = '↓';
    btnDown.style = buttonStyle();
    btnDown.onclick = () => scrollPage(1);

    const btnUp = document.createElement('button');
    btnUp.innerHTML = '↑';
    btnUp.style = buttonStyle();
    btnUp.onclick = () => scrollPage(-1);

    floatWindow.appendChild(btnSettings);
    floatWindow.appendChild(btnDown);
    floatWindow.appendChild(btnUp);
    document.body.appendChild(floatWindow);

    // 悬浮窗拖拽功能
    floatWindow.addEventListener('dragstart', (event) => {
        const style = window.getComputedStyle(event.target, null);
        event.dataTransfer.setData('text/plain',
            (parseInt(style.getPropertyValue('left'), 10) - event.clientX) + ',' +
            (parseInt(style.getPropertyValue('top'), 10) - event.clientY));
    }, false);

    document.body.addEventListener('dragover', (event) => {
        event.preventDefault();
        return false;
    }, false);

    document.body.addEventListener('drop', (event) => {
        const offset = event.dataTransfer.getData('text/plain').split(',');
        const floatWindow = document.querySelector('div[draggable="true"]');
        const left = (event.clientX + parseInt(offset[0], 10)) + 'px';
        const top = (event.clientY + parseInt(offset[1], 10)) + 'px';
        floatWindow.style.left = left;
        floatWindow.style.top = top;
        GM_setValue('floatWindowLeft', left);
        GM_setValue('floatWindowTop', top);
        event.preventDefault();
        return false;
    }, false);
}



    // 滚动页面函数
    function scrollPage(direction) {
        const screenHeight = window.innerHeight;
        const reservedHeight = screenHeight * reservedHeightPercentage / 100;
        window.scrollBy(0, direction * (screenHeight - reservedHeight));
    }

    // 键盘事件监听
    window.addEventListener('keydown', function (event) {
        if (!enableHotkeys) return; // 检查是否启用热键
        const screenHeight = window.innerHeight;
        const reservedHeight = screenHeight * reservedHeightPercentage / 100;
        if ((event.key === upKey || event.key === downKey)) {
            const direction = event.key === downKey ? 1 : -1;
            window.scrollBy(0, direction * (screenHeight - reservedHeight));
            event.preventDefault();
        }
    });

    // 显示设置窗口
    function showSettings() {
        const settingsWindow = document.createElement('div');
        settingsWindow.style = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 300px;
            background-color: ${isBlackMode ? 'black' : 'white'};
            color: ${isBlackMode ? 'white' : 'black'};
            border: 1px solid #ccc;
            z-index: 10001;
            padding: 20px;
            border-radius: 5px;
        `;

        const settingsContainer = document.createElement('div');
        settingsContainer.style = `
            display: flex;
            flex-direction: column;
            align-items: flex-start;
            color: ${isBlackMode ? 'white' : 'black'};
        `;

        // 更新颜色
        const updateColors = () => {
            settingsWindow.style.backgroundColor = isBlackMode ? 'black' : 'white';
            settingsWindow.style.color = isBlackMode ? 'white' : 'black';
            settingsContainer.style.color = isBlackMode ? 'white' : 'black';
            saveButton.style.backgroundColor = isBlackMode ? 'black' : 'white';
            saveButton.style.color = isBlackMode ? 'white' : 'black';
            donateButton.style.backgroundColor = isBlackMode ? 'black' : 'white';
            donateButton.style.color = isBlackMode ? 'white' : 'black';
        };

        // 样式设置
        const createSetting = (labelText, value, onClick) => {
            const container = document.createElement('div');
            container.style = `
                display: flex;
                justify-content: space-between;
                width: 100%;
                margin-bottom: 10px;
                cursor: pointer;
            `;
            container.onclick = onClick;

            const label = document.createElement('span');
            label.innerText = labelText;
            container.appendChild(label);

            const indicator = document.createElement('span');
            indicator.innerText = value ? '✔️' : '✖️';
            container.appendChild(indicator);

            return container;
        };

        const modeSetting = createSetting('🌑黑色模式', isBlackMode, () => {
            isBlackMode = !isBlackMode;
            modeSetting.lastChild.innerText = isBlackMode ? '✔️' : '✖️';
            GM_setValue('isBlackMode', isBlackMode);
            updateColors();
        });

        const createAutoDetectSetting = (labelText, currentOption, optionValue) => {
            const container = document.createElement('div');
            container.style = `
                display: flex;
                justify-content: space-between;
                align-items: center;
                flex: 1;
                margin-bottom: 10px;
                cursor: pointer;
                padding-right: 10px;
            `;
            container.onclick = () => {
                autoDetectMode = optionValue;
                GM_setValue('autoDetectMode', autoDetectMode);
                updateAutoDetectSettings();
            };

            const label = document.createElement('span');
            label.innerText = labelText;
            container.appendChild(label);

            const indicator = document.createElement('span');
            indicator.innerText = (currentOption === optionValue) ? '✔️' : '✖️';
            container.appendChild(indicator);

            return container;
        };
        const updateAutoDetectSettings = () => {
            autoDetectSettingContainer.style = `
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        width: 100%;
    `;
            autoDetectSettingContainer.innerHTML = '';

            // 创建并定义解释文字的DOM元素
            const explanationText = document.createElement('div');
            explanationText.innerText = '🔎自动调整悬浮窗颜色(忽略上方修改)';
            explanationText.style = 'margin-bottom: 10px; display: block; width: 100%; text-align: left;';
            autoDetectSettingContainer.appendChild(explanationText);

            // 创建自动检测设置按钮
            const settingsContainer = document.createElement('div');
            settingsContainer.style = 'display: flex; justify-content: space-between; width: 75%;';
            settingsContainer.appendChild(createAutoDetectSetting('关闭', autoDetectMode, '关闭'));
            settingsContainer.appendChild(createAutoDetectSetting('同色', autoDetectMode, '同色'));
            settingsContainer.appendChild(createAutoDetectSetting('反色', autoDetectMode, '反色'));

            autoDetectSettingContainer.appendChild(settingsContainer);
        };

        const layoutSetting = createSetting('↕️竖向排列按钮', isVerticalLayout, () => {
            isVerticalLayout = !isVerticalLayout;
            layoutSetting.lastChild.innerText = isVerticalLayout ? '✔️' : '✖️';
        });

        const createPercentageInput = (labelText, value, min, max) => {
            const container = document.createElement('div');
            container.style = `
                display: flex;
                justify-content: space-between;
                width: 100%;
                margin-bottom: 10px;
            `;

            const label = document.createElement('label');
            label.innerText = labelText;
            container.appendChild(label);

            const input = document.createElement('input');
            input.type = 'number';
            input.value = value;
            input.min = min;
            input.max = max;
            input.style = `
                width: 50px;
                background-color: ${isBlackMode ? 'black' : 'white'};
                color: ${isBlackMode ? 'white' : 'black'};
            `;

            const percentageLabel = document.createElement('span');
            percentageLabel.innerText = '%';

            container.appendChild(input);
            container.appendChild(percentageLabel);

            return { container, input };
        };

        const sizeInput = createPercentageInput('📏悬浮窗大小', floatWindowSize, 20, 100);
        const percentageInput = createPercentageInput('📄保留页面比例', reservedHeightPercentage, 0, 100);
        const windowOpacityInput = createPercentageInput('🌫️窗口透明度', windowOpacity * 100, 20, 100);
        const textOpacityInput = createPercentageInput('🖋️文字透明度', textOpacity * 100, 20, 100);

        const saveButton = document.createElement('button');
        saveButton.innerHTML = '💾保存';
        saveButton.style = `
            margin-top: 10px;
            background-color: ${isBlackMode ? 'black' : 'white'};
            color: ${isBlackMode ? 'white' : 'black'};
        `;
        saveButton.onclick = () => {
            floatWindowSize = parseInt(sizeInput.input.value, 10);
            reservedHeightPercentage = Math.min(100, Math.max(0, parseInt(percentageInput.input.value, 10)));
            windowOpacity = Math.min(1, Math.max(0.2, parseFloat(windowOpacityInput.input.value) / 100));
            textOpacity = Math.min(1, Math.max(0.2, parseFloat(textOpacityInput.input.value) / 100));
            GM_setValue('floatWindowSize', floatWindowSize);
            GM_setValue('isVerticalLayout', isVerticalLayout);
            GM_setValue('reservedHeightPercentage', reservedHeightPercentage);
            GM_setValue('windowOpacity', windowOpacity);
            GM_setValue('textOpacity', textOpacity);
            document.body.removeChild(settingsWindow);
            location.reload();
        };

        const donateButton = document.createElement('button');
        donateButton.innerHTML = '🔄更新/💰打赏';
        donateButton.style = `
            margin-top: 10px;
            background-color: ${isBlackMode ? 'black' : 'white'};
            color: ${isBlackMode ? 'white' : 'black'};
        `;
        donateButton.onclick = () => {
            if (confirm('⚠️一部分脚本管理器无法自动检测脚本是否有更新,所以需要你去看一下。\n🔄现在的版本号是:v2.0.1。\n💬如果脚本有任何问题,或者你有任何创意,都可以在脚本反馈区留言。\n📄在脚本发布页的介绍部分也放置了我的打赏二维码,\n🥤如果这个脚本帮你解决了大问题,希望你能请我喝杯奶茶哦!')) {
                window.open('https://greasyfork.org/zh-CN/scripts/493257', '_blank');
            }
        };

        const toggleFloatWindow = () => {
            floatWindowVisible = !floatWindowVisible;
            GM_setValue('floatWindowVisible', floatWindowVisible);
            document.body.removeChild(settingsWindow);
            location.reload();
        };

        const confirmToggleFloatWindow = () => {
            if (confirm('❗️确定要关闭悬浮窗吗?\n🖥️电脑端可以通过脚本管理器中的选项重新打开,\n📱若脚本管理器没有图形化界面,可以重新安装脚本。')) {
                toggleFloatWindow();
            }
        };

        const floatWindowSetting = createSetting('📴关闭悬浮窗(长按悬浮窗可以移动)', false, confirmToggleFloatWindow);

        // 分割线
        const createSeparator = () => {
            const separator = document.createElement('hr');
            separator.style = 'width: 100%; margin: 10px 0; border: none; border-top: 1px solid #ccc;';
            return separator;
        };

        settingsContainer.appendChild(modeSetting);

        const hotkeysToggleSetting = createSetting('开启翻页热键功能', enableHotkeys, () => {
            enableHotkeys = !enableHotkeys;
            hotkeysToggleSetting.lastChild.innerText = enableHotkeys ? '✔️' : '✖️';
            GM_setValue('enableHotkeys', enableHotkeys);
        });

        const autoDetectSettingContainer = document.createElement('div');
        settingsContainer.appendChild(autoDetectSettingContainer);
        updateAutoDetectSettings();

        settingsContainer.appendChild(createSeparator());

        settingsContainer.appendChild(layoutSetting);
        settingsContainer.appendChild(sizeInput.container);
        settingsContainer.appendChild(percentageInput.container);
        settingsContainer.appendChild(windowOpacityInput.container);
        settingsContainer.appendChild(textOpacityInput.container);
        settingsContainer.appendChild(floatWindowSetting);

        settingsContainer.appendChild(createSeparator());

        const hotkeySetting = createSetting('🎛️设置电脑端翻页热键', false, () => {
            const hotkeyWindow = document.createElement('div');
            hotkeyWindow.style = `
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 300px;
        background-color: ${isBlackMode ? 'black' : 'white'};
        color: ${isBlackMode ? 'white' : 'black'};
        border: 1px solid #ccc;
        z-index: 10002;
        padding: 20px;
        border-radius: 5px;
    `;

            const hotkeyContainer = document.createElement('div');
            hotkeyContainer.style = `
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        color: ${isBlackMode ? 'white' : 'black'};
    `;

            // 创建并定义解释文字的DOM元素
            const explanationText = document.createElement('div');
            explanationText.innerText = '💬请设置翻页热键\n💡选中文本框后直接按下目标热键试试吧:';
            explanationText.style = 'margin-bottom: 10px; display: block; width: 100%;';
            hotkeyWindow.appendChild(explanationText);

            const createHotkeySetting = (labelText, currentKey, onKeyChange) => {
                const container = document.createElement('div');
                container.style = `
            display: flex;
            justify-content: space-between;
            width: 100%;
            margin-bottom: 10px;
        `;

                const label = document.createElement('label');
                label.innerText = labelText;
                container.appendChild(label);

                const input = document.createElement('input');
                input.type = 'text';
                input.value = currentKey;
                input.style = `
            width: 100px;
            background-color: ${isBlackMode ? 'black' : 'white'};
            color: ${isBlackMode ? 'white' : 'black'};
        `;
                input.onkeydown = (event) => {
                    event.preventDefault();
                    input.value = event.key;
                    onKeyChange(event.key);
                };

                container.appendChild(input);
                return container;
            };

            const upKeySetting = createHotkeySetting('上翻页热键', upKey, (key) => { upKey = key; });
            const downKeySetting = createHotkeySetting('下翻页热键', downKey, (key) => { downKey = key; });

            const hotkeySaveButton = document.createElement('button');
            hotkeySaveButton.innerHTML = '💾保存';
            hotkeySaveButton.style = `
        margin-top: 10px;
        background-color: ${isBlackMode ? 'black' : 'white'};
        color: ${isBlackMode ? 'white' : 'black'};
    `;
            hotkeySaveButton.onclick = () => {
                GM_setValue('upKey', upKey);
                GM_setValue('downKey', downKey);
                document.body.removeChild(hotkeyWindow);
            };

            hotkeyContainer.appendChild(upKeySetting);
            hotkeyContainer.appendChild(downKeySetting);
            hotkeyContainer.appendChild(hotkeySaveButton);

            hotkeyWindow.appendChild(hotkeyContainer);
            document.body.appendChild(hotkeyWindow);
        });

        settingsContainer.appendChild(hotkeysToggleSetting);
        settingsContainer.appendChild(hotkeySetting);

        // 创建按钮容器
        const buttonContainer = document.createElement('div');
        buttonContainer.style = `
    display: flex;
    justify-content: space-between;
    width: 100%;
    margin-top: 10px;
`;

        // 修改保存按钮的样式并添加到按钮容器中
        saveButton.style = `
    flex: 1;
    margin-right: 10px;
    background-color: ${isBlackMode ? 'black' : 'white'};
    color: ${isBlackMode ? 'white' : 'black'};
`;
        buttonContainer.appendChild(saveButton);

        // 修改检查更新/打赏按钮的样式并添加到按钮容器中
        donateButton.style = `
    flex: 1;
    background-color: ${isBlackMode ? 'black' : 'white'};
    color: ${isBlackMode ? 'white' : 'black'};
`;
        buttonContainer.appendChild(donateButton);

        // 将按钮容器添加到设置窗口中
        settingsContainer.appendChild(buttonContainer);

        settingsWindow.appendChild(settingsContainer);
        document.body.appendChild(settingsWindow);

        updateColors();
    }

    // 创建并显示悬浮窗
    createFloatingWindow();

    // 注册菜单命令
    GM_registerMenuCommand('显示悬浮窗', function () {
        GM_setValue('floatWindowVisible', true);
        location.reload();
    });

    // 样式辅助函数
    function buttonStyle() {
        return `
            width: ${floatWindowSize}px;
            height: ${floatWindowSize}px;
            font-size: 20px;
            background-color: ${isBlackMode ? 'black' : 'white'};
            color: ${isBlackMode ? 'white' : 'black'};
            border: none;
            opacity: ${textOpacity};
        `;
    }
})();