// ==UserScript== // @name 📕无动画全屏翻页丨墨水屏一键翻页丨保留比例翻页丨自定义比例 // @version 2.1 // @description 👍忽略滑动动画,快速切换页面,可以通过键盘或浮动窗口进行操作,并调整黑色模式、悬浮窗大小和滑动保留页面比例。 // @author Jingyu0123 // @match *://*/* // @license GPL // @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(btnUp); floatWindow.appendChild(btnDown); 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: 80%;"; 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.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}; `; } })();