视频控制栏自动隐藏

鼠标静止0.1秒后自动隐藏视频控制栏,视频播放时自动隐藏,支持控制栏悬停保持显示

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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兼容版)');
})();