您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
使用xbox 游戏手柄控制微信读书翻页、滚动、全屏
// ==UserScript== // @name Weread gamepad control // @namespace Violentmonkey Scripts // @match https://weread.qq.com/web/reader/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @version 1.2 // @author - // @license GPL 3.0 // @description 使用xbox 游戏手柄控制微信读书翻页、滚动、全屏 // @update update v1.1 增加Y切换全屏功能 // @update update v1.2 增加LB RB 切换主题,X切换亮度功能 // ==/UserScript== var gamepadAPI = { job: 0, update: function () { // 清除按钮缓存 gamepadAPI.buttonsCache = []; // 从上一帧中移动按钮状态到缓存中 for (var k = 0; k < gamepadAPI.buttonsStatus.length; k++) { gamepadAPI.buttonsCache[k] = gamepadAPI.buttonsStatus[k]; } // 清除按钮状态 gamepadAPI.buttonsStatus = []; // 获取 gamepad 对象 var c = navigator.getGamepads()[0]; // 遍历按键,并将按下的按钮加到数组中 var pressed = []; if (c.buttons) { for (var b = 0, t = c.buttons.length; b < c.buttons.length; b++) { if (c.buttons[b].pressed) { // console.log("buttons pressed " + gamepadAPI.buttons[b]) pressed.push(gamepadAPI.buttons[b]); } } } // 遍历坐标值并加到数组中 var axes = []; if (c.axes) { for (var a = 0, x = c.axes.length; a < x; a++) { if (Math.abs(c.axes[a]) > 0.7) { console.log("axes pressed " + gamepadAPI.axes[a]) } axes.push(c.axes[a].toFixed(2)); } } // 分配接收到的值 gamepadAPI.axesStatus = axes; gamepadAPI.buttonsStatus = pressed; // 返回按钮以便调试 return pressed; }, buttonPressed: function (button, hold, released) { var newPress = false; var newRelease = false; // 轮询按下的按钮 for (var i = 0, s = gamepadAPI.buttonsStatus.length; i < s; i++) { // 如果我们找到我们想要的按钮 if (gamepadAPI.buttonsStatus[i] == button) { // 设置布尔变量(newPress)为 true newPress = true; // 如果我们想检查按住还是单次按下 if (!hold) { // 从上一帧轮询缓存状态 for (var j = 0, p = gamepadAPI.buttonsCache.length; j < p; j++) { // 如果按钮(之前)已经被按下了则忽略新的按下状态 if (gamepadAPI.buttonsCache[j] == button) { newPress = false; } } } } } // 检查是不是放开按钮 if (released) { for (var j = 0, p = gamepadAPI.buttonsCache.length; j < p; j++) { if (gamepadAPI.buttonsCache[j] == button) { // 检查当前帧中按钮是否未被按下 if (!gamepadAPI.buttonsStatus.includes(button)) { newRelease = true; } } } } return { pressed: newPress, released: newRelease }; }, buttons: [ 'A', 'B', 'X', 'Y', 'LB', 'RB', 'LT', 'RT', 'Option', 'Start', 'Axis-Left', 'Axis-Right', 'DPad-Up', 'DPad-Down', 'DPad-Left', 'DPad-Right', ], axes: [ 'Left H', 'Left V', 'Right H', 'Right V', ], buttonsCache: [], buttonsStatus: [], axesStatus: [], }; var themes = [ { name: "白雪", value: ["#ffffff", "#000000"] }, { name: "灰绿", value: ["#d8e7eb", "#000000"] }, { name: "浅绿", value: ["#e9faff", "#000000"] }, { name: "明黄", value: ["#ffffed", "#000000"] }, { name: "淡绿", value: ["#eefaee", "#000000"] }, { name: "草绿", value: ["#cce8cf", "#000000"] }, { name: "红粉", value: ["#fcefff", "#000000"] }, { name: "米黄", value: ["#f5f5dc", "#000000"] }, { name: "茶色", value: ["#d2b48c", "#000000"] }, { name: "银色", value: ["#c0c0c0", "#000000"] }, { name: "浅黄", value: ["#f5f1e8", "#000000"] }, { name: "浅灰", value: ["#d9e0e8", "#000000"] }, { name: "午夜", value: ["#002b36", "#839496"] }, { name: "墨水屏", value: ["#c0d3d7", "#111111"] }, { name: "漆黑", value: ["#000000", "#555555"] }, ]; /** * * @param {string} color hex color * @param {number} factor 0-1 * @returns css color */ function darkenColor(color, factor) { function hex2rgb(color) { hex = color.replace('#', ''); let r = parseInt(hex.substr(0, 2), 16); let g = parseInt(hex.substr(2, 2), 16); let b = parseInt(hex.substr(4, 2), 16); return [r, g, b]; } function lab2rgb(lab) { var y = (lab[0] + 16) / 116, x = lab[1] / 500 + y, z = y - lab[2] / 200, r, g, b; x = 0.95047 * ((x * x * x > 0.008856) ? x * x * x : (x - 16 / 116) / 7.787); y = 1.00000 * ((y * y * y > 0.008856) ? y * y * y : (y - 16 / 116) / 7.787); z = 1.08883 * ((z * z * z > 0.008856) ? z * z * z : (z - 16 / 116) / 7.787); r = x * 3.2406 + y * -1.5372 + z * -0.4986; g = x * -0.9689 + y * 1.8758 + z * 0.0415; b = x * 0.0557 + y * -0.2040 + z * 1.0570; r = (r > 0.0031308) ? (1.055 * Math.pow(r, 1 / 2.4) - 0.055) : 12.92 * r; g = (g > 0.0031308) ? (1.055 * Math.pow(g, 1 / 2.4) - 0.055) : 12.92 * g; b = (b > 0.0031308) ? (1.055 * Math.pow(b, 1 / 2.4) - 0.055) : 12.92 * b; return [Math.max(0, Math.min(1, r)) * 255, Math.max(0, Math.min(1, g)) * 255, Math.max(0, Math.min(1, b)) * 255] } function rgb2lab(rgb) { var r = rgb[0] / 255, g = rgb[1] / 255, b = rgb[2] / 255, x, y, z; r = (r > 0.04045) ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92; g = (g > 0.04045) ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92; b = (b > 0.04045) ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92; x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047; y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.00000; z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883; x = (x > 0.008856) ? Math.pow(x, 1 / 3) : (7.787 * x) + 16 / 116; y = (y > 0.008856) ? Math.pow(y, 1 / 3) : (7.787 * y) + 16 / 116; z = (z > 0.008856) ? Math.pow(z, 1 / 3) : (7.787 * z) + 16 / 116; return [(116 * y) - 16, 500 * (x - y), 200 * (y - z)] } let lab = rgb2lab(hex2rgb(color)); console.log("lab color", lab); lab[0] = Math.max(0, lab[0] - lab[0] * factor); let rgb = lab2rgb(lab); console.log("rgb color", rgb); return `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`; } let wechatControl = { next: () => document.querySelector(".renderTarget_pager_button_right").click(), prev: () => document.querySelector(".renderTarget_pager_button:not(.renderTarget_pager_button_right)").click(), readerView: () => document.querySelector(".readerChapterContent"), readerWrap: () => document.querySelector(".readerChapterContent_container"), readerContent: () => document.querySelector(".wr_whiteTheme .readerChapterContent"), topBar: () => document.querySelector(".readerTopBar"), controls: () => document.querySelectorAll(".readerControls_item"), /** @type {number} */ currentTheme: -1, /** @type {Node | null} */ currentCss: null, updateStyle: (direction) => { let prevTheme = null if (wechatControl.currentTheme != -1) { prevTheme = themes[wechatControl.currentTheme] } wechatControl.currentTheme += direction if (wechatControl.currentTheme >= themes.length) wechatControl.currentTheme = 0 let theme = themes[wechatControl.currentTheme].value wechatControl.setTheme(theme) wechatControl.saveTheme() const renderFontColor = () => { const resizeEvent = new Event('resize'); window.dispatchEvent(resizeEvent); } if (!prevTheme || prevTheme.value[1] != theme[1]) { renderFontColor(); } }, dim: 0, darkMode: () => { if (wechatControl.currentTheme == -1) { wechatControl.currentTheme = 0 wechatControl.saveTheme() } if (wechatControl.dim == 0) { wechatControl.dim = 0.3 } else { wechatControl.dim = 0 } wechatControl.updateStyle(0) }, /** * 设置主题 * @param {Array<string>} theme - 主题数组,包含背景色和字体颜色 */ setTheme: (theme) => { console.log("update theme") console.log(theme[0], theme[1]) let color = theme[0] const dim = wechatControl.dim const backgroundColor = darkenColor(color, 0.1 + dim); if (dim != 0) { color = darkenColor(color, dim) } wechatControl.readerView().style.backgroundColor = color; let control_items = wechatControl.controls() for (let i = 0; i < control_items.length; i++) { control_items[i].style.backgroundColor = color; } wechatControl.readerWrap().style.backgroundColor = backgroundColor; wechatControl.topBar().style.backgroundColor = `#00000000`; if (wechatControl.currentCss) { wechatControl.currentCss.remove(); } wechatControl.currentCss = GM_addStyle(` .wr_whiteTheme .readerChapterContent { color: ${theme[1]} !important; } ` ); }, saveTheme: () => { let theme = themes[wechatControl.currentTheme] GM_setValue("theme", theme.name) }, loadTheme: () => { let themeName = GM_getValue("theme") if (themeName) { let theme let index = 0 for (; index < themes.length; index++) { if (themes[index].name == themeName) { theme = themes[index] break } } wechatControl.currentTheme = index wechatControl.setTheme(theme.value) } }, toggleFullScreen: () => { if (!document.fullscreenElement && // 标准方法 !document.mozFullScreenElement && // Firefox !document.webkitFullscreenElement && // Chrome, Safari and Opera !document.msFullscreenElement) { // IE/Edge // 请求全屏 if (document.documentElement.requestFullscreen) { document.documentElement.requestFullscreen(); } else if (document.documentElement.mozRequestFullScreen) { // Firefox document.documentElement.mozRequestFullScreen(); } else if (document.documentElement.webkitRequestFullscreen) { // Chrome, Safari and Opera document.documentElement.webkitRequestFullscreen(); } else if (document.documentElement.msRequestFullscreen) { // IE/Edge document.documentElement.msRequestFullscreen(); } } else { // 退出全屏 if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozCancelFullScreen) { // Firefox document.mozCancelFullScreen(); } else if (document.webkitExitFullscreen) { // Chrome, Safari and Opera document.webkitExitFullscreen(); } else if (document.msExitFullscreen) { // IE/Edge document.msExitFullscreen(); } } }, scroll: (direction) => { const hasVerticalScrollbar = document.documentElement.scrollHeight > document.documentElement.clientHeight; if (hasVerticalScrollbar) { window.scrollTo({ //60 fps top: window.scrollY + ((300 / 60) * direction), behavior: 'instant' }); } } }; (function () { 'use strict'; wechatControl.loadTheme() window.addEventListener("gamepadconnected", (evt) => { console.log('控制器已连接。'); gamepadAPI.job = setInterval(() => { gamepadAPI.update() // 明确调用 buttonPressed 并传递按钮名称 if (gamepadAPI.buttonPressed('A').pressed) { wechatControl.next() } // if (gamepadAPI.buttonPressed('A', true).pressed) { // console.log('A 按钮被持续按下'); // } // if (gamepadAPI.buttonPressed('A', false, true).released) { // console.log('A 按钮被放开'); // } if (gamepadAPI.buttonPressed('B').pressed) { wechatControl.prev(); } if (gamepadAPI.buttonPressed('Y').pressed) { wechatControl.toggleFullScreen(); } if (gamepadAPI.buttonPressed('X').pressed) { wechatControl.darkMode() } if (gamepadAPI.buttonPressed('LB').pressed) { wechatControl.updateStyle(-1) } if (gamepadAPI.buttonPressed('RB').pressed) { wechatControl.updateStyle(1) } if (gamepadAPI.buttonPressed('DPad-Up').pressed) { wechatControl.prev(); } if (gamepadAPI.buttonPressed('DPad-Up', true).pressed) { wechatControl.scroll(-1) } if (gamepadAPI.buttonPressed('DPad-Down').pressed) { wechatControl.next(); } if (gamepadAPI.buttonPressed('DPad-Down', true).pressed) { wechatControl.scroll(1) } if (gamepadAPI.buttonPressed('DPad-Left').pressed) { wechatControl.prev(); } if (gamepadAPI.buttonPressed('DPad-Right').pressed) { wechatControl.next(); } }, 16) }); window.addEventListener("gamepaddisconnected", (evt) => { console.log('控制器已断开。'); clearInterval(gamepadAPI.job) }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址