// ==UserScript== // @name 修复B站播放器性能BUG // @version 2025.07.14.5 // @description 修复 Bilibili 播放器中由于某些 rAF 回调函数引起的性能问题。 // @author 嘉友友 // @match https://www.bilibili.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=bilibili.com // @grant none // @license GNU GPLv3 // @namespace https://greasyfork.org/users/1336389 // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 从本地存储读取状态,默认为开启 let isFixEnabled = localStorage.getItem('bilibili-fix-enabled') !== 'false'; let old_raf = window.requestAnimationFrame; // 保存状态到本地存储 function saveState() { localStorage.setItem('bilibili-fix-enabled', isFixEnabled.toString()); } // 应用修复的函数 function applyFix() { if (isFixEnabled) { window.requestAnimationFrame = (fn) => { let src = ''+fn; if(src.length<1000 && src.includes('.fpsArr.')) { console.log('!!! removed bad rAF'); } else { return old_raf(fn); } }; } else { window.requestAnimationFrame = old_raf; } } // 创建可拖动的开关按钮 function createToggleButton() { const button = document.createElement('div'); button.id = 'bilibili-fix-toggle'; // 从本地存储读取按钮位置 const savedPosition = JSON.parse(localStorage.getItem('bilibili-fix-position') || '{}'); const defaultTop = savedPosition.top || '20px'; const defaultRight = savedPosition.right || '20px'; const defaultLeft = savedPosition.left || 'auto'; const defaultBottom = savedPosition.bottom || 'auto'; button.style.cssText = ` position: fixed; top: ${defaultTop}; right: ${defaultRight}; left: ${defaultLeft}; bottom: ${defaultBottom}; width: 40px; height: 40px; border-radius: 50%; background-color: ${isFixEnabled ? '#1890ff' : '#d9d9d9'}; opacity: 0.6; cursor: move; z-index: 10000; display: flex; align-items: center; justify-content: center; color: white; font-size: 12px; font-weight: bold; user-select: none; transition: all 0.3s ease; box-shadow: 0 2px 8px rgba(0,0,0,0.15); border: 2px solid white; `; button.textContent = '修复'; button.title = `点击${isFixEnabled ? '关闭' : '开启'}修复功能`; // 鼠标悬停效果 button.addEventListener('mouseenter', () => { button.style.opacity = '1'; button.style.transform = 'scale(1.1)'; }); button.addEventListener('mouseleave', () => { button.style.opacity = '0.6'; button.style.transform = 'scale(1)'; }); // 拖动功能 let isDragging = false; let dragStartX, dragStartY; let buttonStartX, buttonStartY; // 保存按钮位置 function savePosition() { const rect = button.getBoundingClientRect(); const position = { top: button.style.top, right: button.style.right, left: button.style.left, bottom: button.style.bottom }; localStorage.setItem('bilibili-fix-position', JSON.stringify(position)); } button.addEventListener('mousedown', (e) => { isDragging = true; dragStartX = e.clientX; dragStartY = e.clientY; buttonStartX = button.offsetLeft; buttonStartY = button.offsetTop; button.style.cursor = 'grabbing'; e.preventDefault(); }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; const deltaX = e.clientX - dragStartX; const deltaY = e.clientY - dragStartY; let newX = buttonStartX + deltaX; let newY = buttonStartY + deltaY; // 限制在窗口范围内 newX = Math.max(0, Math.min(newX, window.innerWidth - button.offsetWidth)); newY = Math.max(0, Math.min(newY, window.innerHeight - button.offsetHeight)); button.style.left = newX + 'px'; button.style.top = newY + 'px'; button.style.right = 'auto'; button.style.bottom = 'auto'; }); document.addEventListener('mouseup', (e) => { if (!isDragging) return; isDragging = false; button.style.cursor = 'move'; // 判断是否为点击而非拖动 const deltaX = Math.abs(e.clientX - dragStartX); const deltaY = Math.abs(e.clientY - dragStartY); if (deltaX < 5 && deltaY < 5) { // 切换开关状态 isFixEnabled = !isFixEnabled; updateButtonAppearance(); applyFix(); saveState(); // 保存状态 console.log(`!!! rAF fix ${isFixEnabled ? 'enabled' : 'disabled'}`); } else { // 如果是拖动,保存位置 savePosition(); } }); function updateButtonAppearance() { button.style.backgroundColor = isFixEnabled ? '#1890ff' : '#d9d9d9'; button.title = `点击${isFixEnabled ? '关闭' : '开启'}修复功能`; } document.body.appendChild(button); return button; } // 等待页面加载完成后创建按钮 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', createToggleButton); } else { createToggleButton(); } // 初始应用修复 applyFix(); console.log(`!!! rAF hook set (${isFixEnabled ? 'enabled' : 'disabled'})`); })();