// ==UserScript== // @name B站自动宽屏居中 // @namespace @ChatGPT // @supportURL https://greasyfork.org/zh-CN/scripts/492413-b%E7%AB%99%E8%87%AA%E5%8A%A8%E5%AE%BD%E5%B1%8F%E5%B1%85%E4%B8%AD/feedback // @homepageURL https://greasyfork.org/zh-CN/scripts/492413-b%E7%AB%99%E8%87%AA%E5%8A%A8%E5%AE%BD%E5%B1%8F%E5%B1%85%E4%B8%AD // @version 1.51 // @description 自动宽屏播放并将播放器垂直居中视口,退出宽屏模式自动滚动页面到顶部。默认关闭自动宽屏。 // @author ChatGPT;ChatGLM;Fittencode;DeepSeek // @license MIT // @match https://*.bilibili.com/* // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @run-at document-end // @downloadURL none // ==/UserScript== (function () { 'use strict'; const elements = { wideBtn: null, webFullBtn: null, fullBtn: null, player: null }; function cacheElements() { elements.wideBtn = document.querySelector('.bpx-player-ctrl-wide'); elements.webFullBtn = document.querySelector('.bpx-player-ctrl-web'); elements.fullBtn = document.querySelector('.bpx-player-ctrl-full'); elements.player = document.querySelector('#bilibili-player'); if (!elements.wideBtn || !elements.webFullBtn || !elements.fullBtn || !elements.player) { console.warn('Some elements not found, retrying...'); setTimeout(cacheElements, 500); } } function waitForElement(selector, callback) { const element = document.querySelector(selector); if (element) { callback(element); return; } const observer = new MutationObserver(() => { const el = document.querySelector(selector); if (el) { callback(el); observer.disconnect(); } }); observer.observe(document, { childList: true, subtree: true }); } function scrollToPosition(topPosition) { window.scrollTo({ top: topPosition, behavior: 'smooth' }); } function scrollToPlayer() { if (elements.player) { const playerTop = elements.player.getBoundingClientRect().top + window.scrollY; const newPosition = playerTop - 75; scrollToPosition(newPosition); } } function scrollToTop() { scrollToPosition(0); } function setWideMode(enable) { if (elements.wideBtn && enable && !elements.wideBtn.classList.contains('bpx-state-entered')) { elements.wideBtn.click(); requestAnimationFrame(scrollToPlayer); } } function handleKeyPress(event) { if (event.key === 'Escape') { handlePlayerStateChange(); } } function registerMenuCommands() { const isEnabled = GM_getValue('enableWideScreen', false); // 默认关闭自动宽屏 const statusText = isEnabled ? '开启' : '关闭'; GM_registerMenuCommand(`自动宽屏(当前:${statusText})`, toggleWideScreen); } function toggleWideScreen() { const enableWideScreen = GM_getValue('enableWideScreen', false); // 默认关闭自动宽屏 const newState = !enableWideScreen; GM_setValue('enableWideScreen', newState); setWideMode(newState); alert(`自动宽屏模式已${newState ? '开启' : '关闭'}`); } function handlePlayerStateChange() { const isWideScreen = elements.wideBtn && elements.wideBtn.classList.contains('bpx-state-entered'); const isFullScreen = document.fullscreenElement || document.webkitFullscreenElement; if (isWideScreen && !isFullScreen) { scrollToPlayer(); } else { scrollToTop(); } } function setupEventListeners() { const buttons = ['.bpx-player-ctrl-wide', '.bpx-player-ctrl-web', '.bpx-player-ctrl-full']; buttons.forEach(selector => { const btn = document.querySelector(selector); if (btn) { btn.addEventListener('click', handlePlayerStateChange); } }); const videoArea = document.querySelector('.bpx-player-video-area'); if (videoArea) { videoArea.addEventListener('dblclick', handlePlayerStateChange); } document.addEventListener('fullscreenchange', handlePlayerStateChange); document.addEventListener('webkitfullscreenchange', handlePlayerStateChange); } function init() { registerMenuCommands(); waitForElement('.bpx-player-ctrl-wide', () => { cacheElements(); setupEventListeners(); setWideMode(GM_getValue('enableWideScreen', false)); // 默认关闭自动宽屏 }); document.addEventListener('keydown', handleKeyPress); const observer = new MutationObserver((mutationsList) => { mutationsList.forEach((mutation) => { if (mutation.type === 'attributes' && mutation.attributeName === 'class') { handlePlayerStateChange(); } }); }); waitForElement('#bilibili-player', (element) => { elements.player = element; observer.observe(element, { attributes: true }); }); } init(); })();