鼠标静止0.1秒后自动隐藏视频控制栏,视频播放时自动隐藏,支持控制栏悬停保持显示
// ==UserScript==
// @name 视频控制栏自动隐藏
// @namespace http://tampermonkey.net/
// @version 1.7
// @description 鼠标静止0.1秒后自动隐藏视频控制栏,视频播放时自动隐藏,支持控制栏悬停保持显示
// @author You
// @match *://*/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// 配置参数
const HIDE_DELAY = 100; // 0.1秒延迟
const VIDEO_SELECTORS = [
'video',
'.video-player',
'.player',
'.video-container',
'.mejs-container',
'.jw-video',
'.plyr__video-wrapper',
'iframe[src*="youtube.com"]',
'iframe[src*="vimeo.com"]',
'.dplayer'
];
let hideTimer = null;
let currentVideo = null;
let controls = null;
let isMouseOverVideo = false;
let isMouseOverControls = false; // 新增:鼠标是否在控制栏上
let lastMouseTime = 0;
let lastMouseX = 0;
let lastMouseY = 0;
let mouseMoveThreshold = 5; // 鼠标移动阈值
let isVideoPlaying = false; // 视频播放状态
// 获取当前时间戳
function getCurrentTime() {
return new Date().getTime();
}
// 查找视频元素
function findVideoElement() {
// 首先查找DPlayer容器
let dplayerElements = document.querySelectorAll('.dplayer');
for (let element of dplayerElements) {
let video = element.querySelector('video');
if (video) {
return element; // 返回DPlayer容器
}
}
// 如果没有找到DPlayer,按常规方式查找
for (let selector of VIDEO_SELECTORS) {
if (selector === '.dplayer') continue; // 已经处理过DPlayer
let elements = document.querySelectorAll(selector);
for (let element of elements) {
if (element.tagName === 'VIDEO' ||
element.querySelector('video')) {
return element;
}
}
}
return null;
}
// 查找控制栏元素 - 增强DPlayer支持
function findControls(video) {
// 常见的视频控制栏选择器
const controlSelectors = [
// DPlayer特有选择器
'.dplayer-controller',
'.dplayer-controller-mask',
'.dplayer-controller-wrap',
'.dplayer-controller-bottom',
'.dplayer-controller-bottom-left',
'.dplayer-controller-bottom-right',
'.dplayer-controller-setting',
'.dplayer-controller-time',
'.dplayer-controller-play',
'.dplayer-controller-danmaku',
'.dplayer-controller-volume',
'.dplayer-controller-full',
// 主要控制栏
'.controls',
'.control-bar',
'.video-controls',
'.mejs-controls',
'.jw-controlbar',
'.plyr__controls',
'.ytp-chrome-bottom',
'.vjs-control-bar',
// 特定播放器控制栏
'.aplayer-controller',
'.video-js .vjs-control-bar',
'.hls-video-controls',
'.video-player-controls',
'.player-controls',
'.control-container',
// 底部控制栏
'.video-bottom-controls',
'.video-progress-bar',
'.video-time',
'.video-play-pause',
'.video-volume',
'.video-fullscreen',
'.video-settings',
'.video-subtitle',
'.video-quality',
'.video-speed',
'.video-progress',
'.video-duration',
'.video-current-time',
'.video-progress-loaded',
'.video-progress-played',
'.video-progress-bar-wrap',
// 通用控制类名
'[class*="control"]',
'[id*="control"]',
// 通用底部控制
'.bottom-controls',
'.progress-controls',
'.time-controls',
'.playback-controls'
];
// 如果是DPlayer容器
if (video.classList.contains('dplayer')) {
// 优先查找DPlayer的控制栏
let dplayerControls = video.querySelector('.dplayer-controller');
if (dplayerControls) {
return dplayerControls;
}
}
// 首先在视频元素内部查找
for (let selector of controlSelectors) {
let controlElements = video.querySelectorAll(selector);
for (let element of controlElements) {
return element; // 返回第一个匹配的元素
}
}
// 尝试通过父元素查找
let parent = video.parentElement;
while (parent && parent !== document.body) {
for (let selector of controlSelectors) {
let control = parent.querySelector(selector);
if (control && control !== video) {
return control;
}
}
parent = parent.parentElement;
}
return null;
}
// 显示控制栏
function showControls() {
if (controls && controls.style) {
controls.style.opacity = '1';
controls.style.visibility = 'visible';
controls.style.transition = 'opacity 0.1s ease, visibility 0.1s';
}
}
// 隐藏控制栏
function hideControls() {
if (controls && controls.style) {
controls.style.opacity = '0';
controls.style.visibility = 'hidden';
controls.style.transition = 'opacity 0.1s ease, visibility 0.1s';
}
}
// 检查鼠标是否移动
function hasMouseMoved(event) {
const deltaX = Math.abs(event.clientX - lastMouseX);
const deltaY = Math.abs(event.clientY - lastMouseY);
const moved = deltaX > mouseMoveThreshold || deltaY > mouseMoveThreshold;
if (moved) {
lastMouseX = event.clientX;
lastMouseY = event.clientY;
lastMouseTime = getCurrentTime();
}
return moved;
}
// 检查鼠标是否静止
function checkMouseIdle() {
const now = getCurrentTime();
const timeSinceLastMove = now - lastMouseTime;
if (timeSinceLastMove >= HIDE_DELAY && isMouseOverVideo && !isMouseOverControls) {
hideControls();
} else if (isMouseOverVideo && !isMouseOverControls) {
// 如果鼠标还在视频区域内且未达到隐藏时间,继续检查
setTimeout(checkMouseIdle, Math.max(10, HIDE_DELAY - timeSinceLastMove));
}
}
// 重置状态
function resetState() {
lastMouseTime = getCurrentTime();
showControls();
if (isMouseOverVideo && !isMouseOverControls) {
// 继续检查鼠标是否静止
setTimeout(checkMouseIdle, HIDE_DELAY);
}
}
// 检查视频播放状态
function checkVideoPlayState() {
// 对于DPlayer,需要特殊处理
if (currentVideo && currentVideo.classList.contains('dplayer')) {
let video = currentVideo.querySelector('video');
if (video) {
isVideoPlaying = !video.paused;
}
} else {
isVideoPlaying = currentVideo && !currentVideo.paused;
}
// 如果视频在播放且鼠标不在视频区域,则隐藏控制栏
if (isVideoPlaying && !isMouseOverVideo && !isMouseOverControls) {
hideControls();
} else if (!isVideoPlaying) {
showControls(); // 如果视频暂停,显示控制栏
}
}
// 鼠标进入视频区域
function handleMouseEnter(e) {
isMouseOverVideo = true;
lastMouseX = e.clientX;
lastMouseY = e.clientY;
lastMouseTime = getCurrentTime();
showControls();
// 开始检查鼠标是否静止
setTimeout(checkMouseIdle, HIDE_DELAY);
}
// 鼠标离开视频区域
function handleMouseLeave() {
isMouseOverVideo = false;
if (hideTimer) {
clearTimeout(hideTimer);
}
// 如果视频正在播放,鼠标离开后隐藏控制栏
if (isVideoPlaying && !isMouseOverControls) {
hideControls();
} else {
showControls(); // 如果视频暂停,保持显示控制栏
}
}
// 鼠标移动事件
function handleMouseMove(e) {
if (!hasMouseMoved(e)) {
return; // 如果鼠标没有实际移动,不触发重置
}
resetState();
}
// 鼠标点击事件
function handleMouseClick() {
resetState();
}
// 视频播放事件
function handleVideoPlay() {
checkVideoPlayState(); // 更新播放状态
// 视频开始播放时,如果鼠标不在视频区域则隐藏控制栏
if (!isMouseOverVideo && !isMouseOverControls) {
setTimeout(() => {
if (isVideoPlaying && !isMouseOverVideo && !isMouseOverControls) {
hideControls();
}
}, 500); // 延迟一点时间,让用户可以看到播放按钮生效
}
}
// 视频暂停事件
function handleVideoPause() {
checkVideoPlayState(); // 更新播放状态
// 视频暂停时显示控制栏
showControls();
}
// 视频时间更新事件(用于检测播放状态变化)
function handleTimeUpdate() {
checkVideoPlayState();
}
// 鼠标进入控制栏(新增)
function handleControlsMouseEnter() {
isMouseOverControls = true;
showControls(); // 确保控制栏显示
// 清除任何可能的隐藏定时器
if (hideTimer) {
clearTimeout(hideTimer);
}
}
// 鼠标离开控制栏(新增)
function handleControlsMouseLeave() {
isMouseOverControls = false;
// 如果鼠标同时不在视频区域,则隐藏控制栏
if (!isMouseOverVideo) {
if (isVideoPlaying) {
hideControls();
} else {
showControls(); // 视频暂停时保持显示
}
} else {
// 如果鼠标在视频区域但不在控制栏上,重新开始计时
resetState();
}
}
// 监听视频元素
function watchVideo(video) {
if (!video) return;
// 查找控制栏
controls = findControls(video);
if (!controls) {
console.log('未找到视频控制栏');
return;
}
// 设置初始样式
controls.style.transition = 'opacity 0.1s ease, visibility 0.1s';
showControls(); // 初始显示控制栏
// 记录初始鼠标位置
lastMouseTime = getCurrentTime();
// 检查播放状态
if (video.classList.contains('dplayer')) {
let actualVideo = video.querySelector('video');
isVideoPlaying = actualVideo ? !actualVideo.paused : false;
} else {
isVideoPlaying = !video.paused;
}
// 添加事件监听器
video.addEventListener('mouseenter', handleMouseEnter);
video.addEventListener('mouseleave', handleMouseLeave);
video.addEventListener('mousemove', handleMouseMove);
video.addEventListener('click', handleMouseClick);
// 对于DPlayer,需要监听内部的video元素
if (video.classList.contains('dplayer')) {
let actualVideo = video.querySelector('video');
if (actualVideo) {
actualVideo.addEventListener('play', handleVideoPlay);
actualVideo.addEventListener('pause', handleVideoPause);
actualVideo.addEventListener('timeupdate', handleTimeUpdate);
}
} else {
video.addEventListener('play', handleVideoPlay);
video.addEventListener('pause', handleVideoPause);
video.addEventListener('timeupdate', handleTimeUpdate);
}
// 为控制栏添加事件监听器(新增)
controls.addEventListener('mouseenter', handleControlsMouseEnter);
controls.addEventListener('mouseleave', handleControlsMouseLeave);
// 如果视频在容器内,也要监听容器
if (video.parentElement && video.parentElement !== document.body) {
video.parentElement.addEventListener('mouseenter', handleMouseEnter);
video.parentElement.addEventListener('mouseleave', handleMouseLeave);
video.parentElement.addEventListener('mousemove', handleMouseMove);
video.parentElement.addEventListener('click', handleMouseClick);
}
currentVideo = video;
console.log('已开始监控视频:', video);
// 检查当前播放状态
checkVideoPlayState();
}
// 检查并监控视频
function checkAndWatchVideo() {
let video = findVideoElement();
if (video && video !== currentVideo) {
// 移除旧的监听器
if (currentVideo) {
currentVideo.removeEventListener('mouseenter', handleMouseEnter);
currentVideo.removeEventListener('mouseleave', handleMouseLeave);
currentVideo.removeEventListener('mousemove', handleMouseMove);
currentVideo.removeEventListener('click', handleMouseClick);
// 移除视频事件监听器
if (currentVideo.classList.contains('dplayer')) {
let actualVideo = currentVideo.querySelector('video');
if (actualVideo) {
actualVideo.removeEventListener('play', handleVideoPlay);
actualVideo.removeEventListener('pause', handleVideoPause);
actualVideo.removeEventListener('timeupdate', handleTimeUpdate);
}
} else {
currentVideo.removeEventListener('play', handleVideoPlay);
currentVideo.removeEventListener('pause', handleVideoPause);
currentVideo.removeEventListener('timeupdate', handleTimeUpdate);
}
if (controls) {
controls.removeEventListener('mouseenter', handleControlsMouseEnter);
controls.removeEventListener('mouseleave', handleControlsMouseLeave);
}
if (currentVideo.parentElement) {
currentVideo.parentElement.removeEventListener('mouseenter', handleMouseEnter);
currentVideo.parentElement.removeEventListener('mouseleave', handleMouseLeave);
currentVideo.parentElement.removeEventListener('mousemove', handleMouseMove);
currentVideo.parentElement.removeEventListener('click', handleMouseClick);
}
}
watchVideo(video);
} else if (video && video === currentVideo) {
// 如果是同一个视频,检查播放状态
checkVideoPlayState();
}
}
// 页面加载完成后立即检查
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', checkAndWatchVideo);
} else {
checkAndWatchVideo();
}
// 页面完全加载后再次检查
window.addEventListener('load', checkAndWatchVideo);
// 定期检查页面中的视频元素
setInterval(checkAndWatchVideo, 1000);
console.log('增强版视频控制栏自动隐藏脚本已加载(DPlayer兼容版)');
})();