Greasy Fork

Greasy Fork is available in English.

视频字幕遮罩条

创建一个磨砂半透明遮罩条来遮挡视频字幕

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         视频字幕遮罩条
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  创建一个磨砂半透明遮罩条来遮挡视频字幕
// @author       Aaron Hu
// @match        *://*/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Create container for the mask
    const container = document.createElement('div');
    Object.assign(container.style, {
        position: 'fixed',
        top: '0',
        left: '0',
        width: '100%',
        height: '100%',
        zIndex: '2147483647',
        pointerEvents: 'none',
        display: 'none',
    });
    document.body.appendChild(container);

    function createMask() {
        const newMask = document.createElement('div');
        Object.assign(newMask.style, {
            position: 'fixed',
            bottom: '30px',
            left: '50%',
            transform: 'translateX(-50%)',
            width: '80%',
            height: '80px',
            backgroundColor: 'rgba(255, 255, 255, 0.2)',
            backdropFilter: 'blur(8px)',
            zIndex: '2147483647',
            cursor: 'move',
            border: '1px solid rgba(255, 255, 255, 0.1)',
            borderRadius: '4px',
            pointerEvents: 'auto',
            userSelect: 'none',
        });

        // Add resizers
        const leftResizer = document.createElement('div');
        const rightResizer = document.createElement('div');
        const topResizer = document.createElement('div');

        // Style for horizontal resizers
        const horizontalResizerStyle = {
            position: 'absolute',
            top: '0',
            width: '10px',
            height: '100%',
            cursor: 'ew-resize',
            backgroundColor: 'rgba(255, 255, 255, 0.3)',
            borderRadius: '4px',
        };

        Object.assign(leftResizer.style, {
            ...horizontalResizerStyle,
            left: '-5px',
        });

        Object.assign(rightResizer.style, {
            ...horizontalResizerStyle,
            right: '-5px',
        });

        // Style for vertical resizer
        Object.assign(topResizer.style, {
            position: 'absolute',
            top: '-5px',
            left: '50%',
            transform: 'translateX(-50%)',
            width: '40px',
            height: '10px',
            backgroundColor: 'rgba(255, 255, 255, 0.3)',
            cursor: 'ns-resize',
            borderRadius: '4px',
        });

        // Add resize functionality
        let isResizing = false;
        let currentResizer = null;
        let initialWidth, initialHeight, initialX, initialY, initialBottom, initialTop;

        function startResize(e, resizer) {
            isResizing = true;
            currentResizer = resizer;
            const rect = newMask.getBoundingClientRect();
            initialWidth = rect.width;
            initialHeight = rect.height;
            initialX = e.clientX;
            initialY = e.clientY;
            initialBottom = rect.bottom;
            initialTop = rect.top;
            e.stopPropagation();
        }

        function resize(e) {
            if (!isResizing) return;
            e.preventDefault();

            if (currentResizer === leftResizer || currentResizer === rightResizer) {
                // 计算鼠标移动距离
                const deltaX = e.clientX - initialX;

                // 从中心点同时调整两侧
                const widthChange = deltaX * 2;
                const newWidth = initialWidth + widthChange;

                if (newWidth > 100) {
                    newMask.style.width = `${newWidth}px`;
                    // 保持中心点不变
                    const centerX = window.innerWidth / 2;
                    newMask.style.left = '50%';
                    newMask.style.transform = 'translateX(-50%)';
                }
            } else if (currentResizer === topResizer) {
                const mouseY = e.clientY;
                const deltaY = mouseY - initialY;

                // 跟随鼠标移动方向自然变化
                if (deltaY > 0) { // 向下移动,增加高度
                    const newHeight = initialHeight + deltaY;
                    if (newHeight > 20) {
                        newMask.style.height = `${newHeight}px`;
                        newMask.style.bottom = `${initialBottom - window.innerHeight}px`;
                    }
                } else { // 向上移动,减少高度
                    const newHeight = initialHeight - Math.abs(deltaY);
                    if (newHeight > 20) {
                        newMask.style.height = `${newHeight}px`;
                        newMask.style.bottom = `${initialBottom - window.innerHeight}px`;
                    }
                }
            }
        }

        function stopResize() {
            isResizing = false;
            currentResizer = null;
        }

        leftResizer.addEventListener('mousedown', (e) => startResize(e, leftResizer));
        rightResizer.addEventListener('mousedown', (e) => startResize(e, rightResizer));
        topResizer.addEventListener('mousedown', (e) => startResize(e, topResizer));
        document.addEventListener('mousemove', resize);
        document.addEventListener('mouseup', stopResize);

        // Add close button
        const closeButton = document.createElement('div');
        Object.assign(closeButton.style, {
            position: 'absolute',
            top: '5px',
            right: '5px',
            width: '20px',
            height: '20px',
            backgroundColor: 'red',
            color: 'white',
            textAlign: 'center',
            lineHeight: '20px',
            borderRadius: '50%',
            cursor: 'pointer',
            zIndex: '2147483648',
        });
        closeButton.textContent = '×';
        closeButton.addEventListener('click', () => {
            container.removeChild(newMask);
        });

        // Append all elements
        newMask.appendChild(closeButton);
        newMask.appendChild(leftResizer);
        newMask.appendChild(rightResizer);
        newMask.appendChild(topResizer);

        // Add drag functionality
        let isDragging = false;
        let initialDragX, initialDragY;

        newMask.addEventListener('mousedown', (e) => {
            if (e.target !== newMask) return;
            const rect = newMask.getBoundingClientRect();
            initialDragX = e.clientX - rect.left;
            initialDragY = e.clientY - rect.top;
            isDragging = true;
        });

        document.addEventListener('mousemove', (e) => {
            if (!isDragging) return;
            e.preventDefault();
            const x = e.clientX - initialDragX;
            const y = e.clientY - initialDragY;
            newMask.style.left = `${x}px`;
            newMask.style.top = `${y}px`;
            newMask.style.transform = 'none';
        });

        document.addEventListener('mouseup', () => {
            isDragging = false;
        });

        return newMask;
    }

    // 切换显示状态的函数
    function toggleMask() {
        const isVisible = container.style.display === 'none';
        container.style.display = isVisible ? 'block' : 'none';

        // 如果切换为显示状态且容器内没有遮罩条,则创建一个
        if (isVisible && container.children.length === 0) {
            const newMask = createMask();
            container.appendChild(newMask);
        }
    }

    function addNewMask() {
        container.style.display = 'block'; // 确保容器可见
        const newMask = createMask();
        container.appendChild(newMask);
    }

    function clearAllMasks() {
        while (container.firstChild) {
            container.removeChild(container.firstChild);
        }
        container.style.display = 'none'; // 清空后隐藏容器
    }

    // Register Tampermonkey menu commands
    GM_registerMenuCommand('切换显示', toggleMask);
    GM_registerMenuCommand('新增遮罩条', addNewMask);
    GM_registerMenuCommand('一键清空', clearAllMasks);

    // 处理全屏
    function handleFullscreen() {
        const fullscreenElement = document.fullscreenElement ||
                                document.webkitFullscreenElement ||
                                document.mozFullScreenElement ||
                                document.msFullscreenElement;

        if (fullscreenElement) {
            fullscreenElement.appendChild(container);
            container.style.position = 'absolute';
        } else {
            document.body.appendChild(container);
            container.style.position = 'fixed';
        }
    }

    document.addEventListener('fullscreenchange', handleFullscreen);
    document.addEventListener('webkitfullscreenchange', handleFullscreen);
    document.addEventListener('mozfullscreenchange', handleFullscreen);
    document.addEventListener('MSFullscreenChange', handleFullscreen);
})();