Greasy Fork is available in English.
创建一个磨砂半透明遮罩条来遮挡视频字幕
当前为
// ==UserScript==
// @name 视频字幕遮罩条
// @namespace http://tampermonkey.net/
// @version 1.4
// @description 创建一个磨砂半透明遮罩条来遮挡视频字幕
// @author Aaron Hu
// @match *://*/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addStyle
// @grant GM_registerMenuCommand
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 检查页面是否包含视频元素
const hasVideo = document.querySelector('video');
if (!hasVideo) {
console.log('页面中没有视频元素');
return;
}
// 检查是否已经存在遮罩条
if (document.querySelector('#subtitle-mask-container')) {
console.log('遮罩条已存在');
return;
}
// 创建容器和遮罩条
const container = document.createElement('div');
container.id = 'subtitle-mask-container'; // 为容器添加唯一ID
const mask = document.createElement('div');
// 创建关闭按钮
const closeButton = document.createElement('div');
closeButton.innerHTML = '×'; // 使用乘号符号作为关闭按钮
Object.assign(closeButton.style, {
position: 'absolute',
top: '5px',
right: '5px',
width: '20px',
height: '20px',
backgroundColor: 'rgba(255, 255, 255, 0.7)',
color: 'black',
textAlign: 'center',
lineHeight: '20px',
borderRadius: '50%',
cursor: 'pointer',
zIndex: '2147483648', // 确保在遮罩条之上
});
// 添加关闭按钮的点击事件
closeButton.addEventListener('click', () => {
container.remove();
GM_setValue('maskVisible', false); // 更新存储状态
});
// 将关闭按钮添加到遮罩条
mask.appendChild(closeButton);
// 从存储中获取显示状态和位置信息
let isVisible = GM_getValue('maskVisible', false);
let maskConfig = GM_getValue('maskConfig', {
width: '80%',
height: '80px',
bottom: '30px',
xOffset: 0
});
// 设置容器样式
Object.assign(container.style, {
position: 'fixed',
top: '0',
left: '0',
width: '100%',
height: '100%',
zIndex: '2147483647',
pointerEvents: 'none',
display: isVisible ? 'block' : 'none'
});
// 设置遮罩条的样式
Object.assign(mask.style, {
position: 'fixed',
bottom: maskConfig.bottom,
left: '50%',
transform: `translateX(calc(-50% + ${maskConfig.xOffset}px))`,
width: maskConfig.width,
height: maskConfig.height,
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',
});
// 添加切换显示状态的函数
function toggleMask() {
isVisible = !isVisible;
GM_setValue('maskVisible', isVisible);
container.style.display = isVisible ? 'block' : 'none';
}
// 注册油猴菜单命令
GM_registerMenuCommand('切换遮罩条显示', toggleMask);
// 监听油猴脚本的启用/禁用状态
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.attributeName === 'disabled') {
const scriptTag = document.querySelector('script[src*="subtitle-mask.user.js"]');
if (scriptTag) {
const isEnabled = !scriptTag.hasAttribute('disabled');
container.style.display = isEnabled && isVisible ? 'block' : 'none';
}
}
});
});
// 观察脚本标签的变化
const scriptTag = document.querySelector('script[src*="subtitle-mask.user.js"]');
if (scriptTag) {
observer.observe(scriptTag, {
attributes: true,
attributeFilter: ['disabled']
});
}
// 修改拖动功能的代码部分
let isDragging = false;
let currentX, currentY;
let initialX, initialY;
let xOffset = 0, yOffset = 0;
mask.addEventListener('mousedown', dragStart);
document.addEventListener('mousemove', drag);
document.addEventListener('mouseup', dragEnd);
function dragStart(e) {
// 记录鼠标按下时的初始位置
const rect = mask.getBoundingClientRect();
xOffset = rect.left + rect.width / 2; // 考虑元素的中心点
yOffset = window.innerHeight - rect.top - rect.height / 2; // 从底部计算偏移
initialX = e.clientX - (rect.left + rect.width / 2);
initialY = e.clientY - (rect.top + rect.height / 2);
isDragging = true;
}
function drag(e) {
if (!isDragging) return;
e.preventDefault();
// 计算新位置
const x = e.clientX - initialX - window.innerWidth / 2;
const y = window.innerHeight - (e.clientY - initialY) - mask.offsetHeight / 2;
// 更新位置
mask.style.left = '50%';
mask.style.bottom = `${y}px`;
mask.style.transform = `translate(calc(-50% + ${x}px), 0)`;
// 保存位置信息
maskConfig.bottom = `${y}px`;
maskConfig.xOffset = x;
GM_setValue('maskConfig', maskConfig);
}
function dragEnd() {
isDragging = false;
}
// 添加左右两侧的宽度调节器
const leftResizer = document.createElement('div');
const rightResizer = document.createElement('div');
// 设置调节器的基础样式
const resizerStyles = {
position: 'absolute',
top: '0',
width: '10px',
height: '100%',
backgroundColor: 'rgba(255, 255, 255, 0.3)',
cursor: 'ew-resize',
borderRadius: '4px',
};
// 设置左侧调节器
Object.assign(leftResizer.style, {
...resizerStyles,
left: '-5px',
});
// 设置右侧调节器
Object.assign(rightResizer.style, {
...resizerStyles,
right: '-5px',
});
// 宽度调节相关变量
let isResizingWidth = false;
let resizingSide = null;
let initialWidth;
let initialMouseX;
// 开始调节宽度
function widthResizeStart(e, side) {
isResizingWidth = true;
resizingSide = side;
initialWidth = mask.offsetWidth;
initialMouseX = e.clientX;
e.stopPropagation();
}
// 调节宽度过程
function widthResize(e) {
if (!isResizingWidth) return;
e.preventDefault();
const deltaX = e.clientX - initialMouseX;
const newWidth = resizingSide === 'right'
? initialWidth + deltaX
: initialWidth - deltaX;
// 设置最小宽度限制为100px
if (newWidth > 100) {
mask.style.width = `${newWidth}px`;
if (resizingSide === 'left') {
// 左侧调节时保持中心点不变
const xAdjustment = deltaX / 2;
mask.style.transform = `translateX(calc(-50% + ${xAdjustment}px))`;
maskConfig.xOffset = xAdjustment;
}
maskConfig.width = `${newWidth}px`;
GM_setValue('maskConfig', maskConfig);
}
}
// 结束调节宽度
function widthResizeEnd() {
isResizingWidth = false;
resizingSide = null;
}
// 添加事件监听
leftResizer.addEventListener('mousedown', (e) => widthResizeStart(e, 'left'));
rightResizer.addEventListener('mousedown', (e) => widthResizeStart(e, 'right'));
document.addEventListener('mousemove', widthResize);
document.addEventListener('mouseup', widthResizeEnd);
// 将调节器添加到遮罩条
mask.appendChild(leftResizer);
mask.appendChild(rightResizer);
// 在宽度调节器代码后添加高度调节器代码
const heightResizer = document.createElement('div');
// 设置高度调节器的样式
Object.assign(heightResizer.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',
});
// 高度调节相关变量
let isResizingHeight = false;
let initialHeight;
let initialMouseY;
// 开始调节高度
function heightResizeStart(e) {
isResizingHeight = true;
initialHeight = mask.offsetHeight;
initialMouseY = e.clientY;
e.stopPropagation();
}
// 调节高度过程
function heightResize(e) {
if (!isResizingHeight) return;
e.preventDefault();
const deltaY = initialMouseY - e.clientY;
const newHeight = initialHeight + deltaY;
// 设置最小高度限制为20px
if (newHeight > 20) {
mask.style.height = `${newHeight}px`;
maskConfig.height = `${newHeight}px`;
GM_setValue('maskConfig', maskConfig);
}
}
// 结束调节高度
function heightResizeEnd() {
isResizingHeight = false;
}
// 添加高度调节相关的事件监听
heightResizer.addEventListener('mousedown', heightResizeStart);
document.addEventListener('mousemove', heightResize);
document.addEventListener('mouseup', heightResizeEnd);
// 将高度调节器添加到遮罩条
mask.appendChild(heightResizer);
// 确保遮罩条立即显示
container.style.display = isVisible ? 'block' : 'none';
container.appendChild(mask);
document.body.appendChild(container);
// 添加调试信息
console.log('遮罩条已创建', {
isVisible,
containerDisplay: container.style.display,
maskStyles: mask.style,
containerStyles: container.style
});
// 添加全屏检测和处理
document.addEventListener('fullscreenchange', handleFullscreen);
document.addEventListener('webkitfullscreenchange', handleFullscreen);
document.addEventListener('mozfullscreenchange', handleFullscreen);
document.addEventListener('MSFullscreenChange', handleFullscreen);
function handleFullscreen() {
const fullscreenElement = document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement;
if (fullscreenElement) {
// 在全屏元素内重新添加遮罩
fullscreenElement.appendChild(container);
} else {
// 退出全屏时重新添加到 body
document.body.appendChild(container);
}
}
})();