// ==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 // @downloadURL none // ==/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}; `; } })();