// ==UserScript== // @name 字幕遮挡条 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 毛玻璃效果的字幕遮挡条,如果你看美剧英剧且不想看中文字幕的话,且快捷键V键可以快速启动 // @author Cup Noodle // @license MIT // @match *://*/* // @grant GM_addStyle // @downloadURL https://update.greasyfork.icu/scripts/528824/%E5%AD%97%E5%B9%95%E9%81%AE%E6%8C%A1%E6%9D%A1.user.js // @updateURL https://update.greasyfork.icu/scripts/528824/%E5%AD%97%E5%B9%95%E9%81%AE%E6%8C%A1%E6%9D%A1.meta.js // ==/UserScript== (function () { 'use strict'; GM_addStyle(` #bilibili-overlay-btn { position: fixed !important; right: 20px !important; bottom: 20px !important; z-index: 9999 !important; padding: 8px 12px !important; background-color: rgba(255,255,255,0.9) !important; border: 1px solid #ddd !important; border-radius: 4px !important; cursor: pointer !important; font-size: 14px !important; transition: left 0.2s, top 0.2s; } `); const button = document.createElement('div'); button.id = 'bilibili-overlay-btn'; button.textContent = '◼️ 字幕遮挡层'; document.body.appendChild(button); const shortcutTip = document.createElement('div'); shortcutTip.id = 'shortcut-tip'; shortcutTip.textContent = '按 V 键'; document.body.appendChild(shortcutTip); const overlay = document.createElement('div'); overlay.style.position = 'fixed'; const savedPosition = localStorage.getItem('overlayPosition'); if (savedPosition) { const { top, left, width, height } = JSON.parse(savedPosition); overlay.style.top = top; overlay.style.left = left; overlay.style.width = width; overlay.style.height = height; } else { overlay.style.top = '200px'; overlay.style.left = '200px'; overlay.style.width = '900px'; overlay.style.height = '45px'; } overlay.style.backgroundColor = 'white'; overlay.style.zIndex = '999999999999'; overlay.style.cursor = 'default'; overlay.style.display = 'none'; overlay.style.borderRadius = '10px'; overlay.style.background = 'rgba(255,255,255,0.1)'; overlay.style.backdropFilter = 'blur(10px)'; overlay.style.webkitBackdropFilter = 'blur(10px)'; document.body.appendChild(overlay); let isDragging = false; let dragStartX, dragStartY; overlay.addEventListener('mousedown', function (e) { const rect = overlay.getBoundingClientRect(); const isEdge = ( e.clientX >= rect.right - 10 && e.clientY >= rect.bottom - 10 ); if (!isEdge) { isDragging = true; dragStartX = e.clientX - parseInt(overlay.style.left, 10); dragStartY = e.clientY - parseInt(overlay.style.top, 10); document.body.style.cursor = 'move'; } }); document.addEventListener('mousemove', function (e) { if (isDragging) { overlay.style.left = (e.clientX - dragStartX) + 'px'; overlay.style.top = (e.clientY - dragStartY) + 'px'; } }); document.addEventListener('mouseup', function () { if (isDragging) { isDragging = false; document.body.style.cursor = 'default'; localStorage.setItem('overlayPosition', JSON.stringify({ top: overlay.style.top, left: overlay.style.left, width: overlay.style.width, height: overlay.style.height })); } }); function addResizableEffect(element) { const minWidth = 100; const minHeight = 10; element.onmousemove = function (e) { const rect = element.getBoundingClientRect(); if (e.clientX > rect.left + rect.width - 10 || rect.left + 10 > e.clientX) { element.style.cursor = 'w-resize'; } else if (e.clientY > rect.top + rect.height - 10) { element.style.cursor = 's-resize'; } else if (e.clientY > rect.top && e.clientY < rect.top + 10) { element.style.cursor = 'n-resize'; } else { element.style.cursor = 'default'; } }; element.onmousedown = (e) => { const clientX = e.clientX; const clientY = e.clientY; const elW = element.clientWidth; const elH = element.clientHeight; const EloffsetLeft = element.offsetLeft; const EloffsetTop = element.offsetTop; element.style.userSelect = 'none'; const isTopResize = clientY > EloffsetTop && clientY < EloffsetTop + 10; document.onmousemove = function (e) { e.preventDefault(); if (clientX > EloffsetLeft && clientX < EloffsetLeft + 10) { const newWidth = elW - (e.clientX - clientX); if (newWidth >= minWidth) { element.style.width = newWidth + 'px'; element.style.left = EloffsetLeft + (e.clientX - clientX) + 'px'; } } if (clientX > EloffsetLeft + elW - 10 && clientX < EloffsetLeft + elW) { const newWidth = elW + (e.clientX - clientX); if (newWidth >= minWidth) { element.style.width = newWidth + 'px'; } } if (clientY > EloffsetTop + elH - 10 && clientY < EloffsetTop + elH) { const newHeight = elH + (e.clientY - clientY); if (newHeight >= minHeight) { element.style.height = newHeight + 'px'; } } if (isTopResize) { const newHeight = elH - (e.clientY - clientY); if (newHeight >= minHeight) { element.style.height = newHeight + 'px'; element.style.top = EloffsetTop + (e.clientY - clientY) + 'px'; } } }; document.onmouseup = function (e) { document.onmousemove = null; document.onmouseup = null; localStorage.setItem('overlayPosition', JSON.stringify({ top: overlay.style.top, left: overlay.style.left, width: overlay.style.width, height: overlay.style.height })); }; }; } addResizableEffect(overlay); function applyStyles() { overlay.style.backdropFilter = `blur(10px)`; overlay.style.background = 'rgba(255,255,255,0.1)'; } function toggleOverlay() { overlay.style.display = overlay.style.display === 'none' ? '' : 'none'; button.textContent = overlay.style.display === '' ? '隐藏遮挡层' : '◼️ 字幕遮挡层'; applyStyles(); } button.addEventListener('click', toggleOverlay); shortcutTip.addEventListener('click', toggleOverlay); document.addEventListener('keydown', function (e) { if (e.key === 'v' || e.key === 'V') { toggleOverlay(); } }); function requestFullscreen(element) { if (element.requestFullscreen) { element.requestFullscreen(); } else if (element.webkitRequestFullscreen) { element.webkitRequestFullscreen(); } else if (element.mozRequestFullScreen) { element.mozRequestFullScreen(); } else if (element.msRequestFullscreen) { element.msRequestFullscreen(); } } function exitFullscreen() { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } } const container = document.querySelector('.container'); if (container) { const video = container.querySelector('video'); if (video) { const fullscreenButton = video.parentNode.querySelector('.vjs-fullscreen-control'); if (fullscreenButton) { fullscreenButton.addEventListener('click', function (e) { e.preventDefault(); if (document.fullscreenElement === container) { exitFullscreen(); } else { requestFullscreen(container); } }); } } } document.addEventListener('fullscreenchange', function () { if (document.fullscreenElement) { button.style.display = 'none'; shortcutTip.style.display = 'none'; overlay.style.zIndex = '999999999999'; const container = document.fullscreenElement || document.body; container.appendChild(overlay); } else { button.style.display = 'block'; shortcutTip.style.display = 'block'; } }); const observer = new MutationObserver((mutationsList) => { for (const mutation of mutationsList) { if (mutation.type === 'attributes' && mutation.attributeName === 'class') { const videoWrapper = document.querySelector('.bpx-player-container'); if (videoWrapper && videoWrapper.classList.contains('bpx-player-container-web-fullscreen')) { button.style.display = 'none'; shortcutTip.style.display = 'none'; overlay.style.zIndex = '999999999999'; } else { button.style.display = 'block'; shortcutTip.style.display = 'block'; } } } }); const videoWrapper = document.querySelector('.bpx-player-container'); if (videoWrapper) { observer.observe(videoWrapper, { attributes: true, attributeFilter: ['class'] }); } })();