悬浮调速区域即可用滚轮调整速度,无视觉干扰
// ==UserScript==
// @name bilibili播放器滚轮调播放速
// @namespace http://tampermonkey.net/
// @version 3.1
// @description 悬浮调速区域即可用滚轮调整速度,无视觉干扰
// @author dashsag
// @match *://*/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
let currentSpeed = 1.00;
let isHovering = false;
let menuElement = null;
// 创建无提示的菜单项
const createStealthItem = () => {
const li = document.createElement('li');
li.className = 'bpx-player-ctrl-playbackrate-menu-item';
li.style.cssText = 'cursor: ns-resize; height: 22px; opacity: 0.8;';
li.dataset.stealth = 'true';
return li;
};
// 隐式更新显示
const stealthUpdate = () => {
// 查找现有标准菜单项
const defaultItems = document.querySelectorAll('.bpx-player-ctrl-playbackrate-menu-item:not([data-stealth])');
// 同步激活状态
defaultItems.forEach(item => {
const itemSpeed = parseFloat(item.dataset.value || 1);
item.classList.toggle('active', itemSpeed === currentSpeed);
});
// 更新视频播放速率显示
const video = document.querySelector('video');
if (video) video.playbackRate = currentSpeed;
};
// 滚轮处理
const handleWheel = (e) => {
if (!isHovering) return;
e.preventDefault();
const delta = e.deltaY < 0 ? 0.02 : -0.02;
currentSpeed = parseFloat((currentSpeed + delta).toFixed(2));
currentSpeed = Math.min(16.00, Math.max(0.10, currentSpeed));
stealthUpdate();
};
// 智能悬停检测
const checkHoverState = () => {
if (!menuElement) return;
const rect = menuElement.getBoundingClientRect();
isHovering = !!(rect.width && rect.height &&
getComputedStyle(menuElement).visibility !== 'hidden');
};
// 初始化
const observer = new MutationObserver(() => {
const menu = document.querySelector('.bpx-player-ctrl-playbackrate-menu');
if (menu && !menu.dataset.stealth) {
menuElement = menu;
menu.dataset.stealth = 'true';
// 添加透明触发区域
menu.prepend(createStealthItem());
// 事件监听
menu.addEventListener('wheel', handleWheel, { passive: false });
menu.addEventListener('mouseenter', checkHoverState);
menu.addEventListener('mouseleave', () => isHovering = false);
// 视频同步
const video = document.querySelector('video');
if (video) {
currentSpeed = video.playbackRate;
video.addEventListener('ratechange', () => {
currentSpeed = parseFloat(video.playbackRate.toFixed(2));
});
}
// 状态轮询
setInterval(checkHoverState, 300);
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['class', 'style']
});
})();