您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
哔哩哔哩宽屏体验
当前为
// ==UserScript== // @name 哔哩哔哩宽屏 // @name:en Wider Bilibili // @namespace https://gf.qytechs.cn/users/1125570 // @description 哔哩哔哩宽屏体验 // @description:en BiliBili, but wider // @version 0.3.4 // @author posthumz // @license MIT // @match http*://*.bilibili.com/* // @icon https://www.bilibili.com/favicon.ico // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM_addValueChangeListener // @noframes // ==/UserScript== (async function() { 'use strict' const styles = { home: `.feed-card, .floor-single-card, .bili-video-card { margin-top: 0px !important; } .feed-roll-btn { left: initial !important; right: calc(10px - var(--layout-padding)); } .palette-button-outer { padding: 0; } .palette-button-wrap { left: initial !important; right: 10px; }`, t: `.bili-dyn-home--member { margin: 0 var(--layout-padding) !important; main { flex: 1 } } `, read: `.article-detail { width: 90%; .article-up-info { width: initial; margin: 0 80px 20px; } .right-side-bar { right: 0; } }`, video: `/* 播放器 */ #bilibili-player { position: relative; z-index: 1; width: 100%; height: 100%; } #playerWrap, #bilibili-player-wrap { position: relative; height: 100vh; min-height: 20vh; padding: 0; } /* 小窗以视频长宽比为准,不显示黑边和阴影 */ .bpx-player-container[data-screen="mini"] { height: auto !important; box-shadow: none; } .bpx-player-container:not([data-screen="mini"]) { width: 100% !important; } /* 视频标题换行显示 */ #viewbox_report { height: auto; } .video-title { white-space: normal !important; } /* 视频页、番剧页、收藏/稍后再看页的下方容器 */ .video-container-v1, .main-container, .playlist-container { z-index: 0; padding: 0 var(--layout-padding); } .left-container, .plp-l, .playlist-container--left { flex: 1; } /* 不然无评论时小窗无法显示 */ .left-container { min-height: calc(100vh + 80px) !important; } .plp-r { padding-top: 0 !important; } /* 番剧/影视页下方容器 */ .main-container { width: 100%; margin: 0; padding: 15px 50px 15px 25px !important; box-sizing: border-box; display: flex; } .player-left-components { padding-right: 30px !important; } .toolbar { padding-top: 0; } /* 播放器控件 */ .bpx-player-top-left-title, .bpx-player-top-left-music { display: block !important; } .bpx-player-control-bottom { padding: 0 24px; } .bpx-player-control-bottom-left, .bpx-player-control-bottom-right, .bpx-player-sending-bar, .be-video-control-bar-extend { gap: 10px; >:not(.bpx-player-ctrl-time) { width: auto !important; margin: 0 !important; } } .bpx-player-control-bottom-left { min-width: initial !important; } .bpx-player-control-bottom-center { padding: 0 30px !important; } .bpx-player-control-bottom-right { min-width: initial !important; >div { padding: 0 !important; } } .bpx-player-ctrl-time-label { text-align: center !important; text-indent: 0 !important; } .bpx-player-ctrl-time, .bpx-player-ctrl-quality { margin-right: 0 !important; } .bpx-player-video-inputbar { min-width: initial !important; } /* 右下方浮动按钮 */ div[class^=navTools_floatNav] { z-index: 1 !important; } /* 笔记位移 (不然笔记会超出页面初始范围) */ .note-pc { transform: translate(-12px, 64px); } /* 导航栏 (兼容Bilibili Evolved自定义导航栏) */ #biliMainHeader, .custom-navbar { position: sticky !important; top: 0; z-index: 3 !important; } #biliMainHeader > .bili-header { min-height: 0 !important; } .bili-header__bar { position: relative !important; } /* Bilibili Evolved 夜间模式修正 */ .bpx-player-container .bpx-player-sending-bar { background-color: transparent !important; } .bpx-player-container .bpx-player-video-info { color: hsla(0,0%,100%,.9) !important; } .bpx-player-container .bpx-player-sending-bar .bpx-player-video-btn-dm, .bpx-player-container .bpx-player-sending-bar .bpx-player-dm-setting, .bpx-player-container .bpx-player-sending-bar .bpx-player-dm-switch { fill: hsla(0,0%,100%,.9) !important; } /* Bilibili Evolved侧栏 */ .be-settings { z-index: 3; position: fixed; }`, mini: `.bpx-player-container { min-width: 180px; } .bpx-player-mini-resizer { position: absolute; left: 0; width: 10px; height: 100%; cursor: ew-resize; }`, common: `:root { --layout-padding: ${GM_getValue('左右边距', 30)}px; } /* 搜索栏 */ .center-search-container { min-width: 0; } .nav-search-input { padding-right: 0; } .nav-search-clean { display: none; } /* 脚本设置样式 */ #WBOptions { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 114514; border-radius: 15px; padding: 20px; display: none; grid-template-columns: repeat(2, 1fr); gap: 20px 30px; background-color: var(--bg1); color: var(--text1); outline: 4px solid #00a0d8; font-size: 18px; } #WBOptionsClose { position: absolute; border: none; right: 0; font-size: 30px; line-height: 30px; width: 30px; border-top-right-radius: 15px; border-bottom-left-radius: 5px; transition: .1s; background-color: transparent; color: var(--text1); } #WBOptionsClose:hover { background-color: #e81123; } #WBOptionsClose:active { opacity: 0.5; } #WBOptions>header { grid-column: 1/-1; } #WBOptions>label { align-items: center; display: flex; gap: 10px; } #WBOptions input { height: 20px; margin: 0; padding: 4px !important; box-sizing: content-box !important; } .slider::before { content: ""; display: block; position: relative; height: 100%; aspect-ratio: 1/1; border-radius: 50%; background-color: #fff; transition: .4s; } .slider { appearance: none; width: 40px; border-radius: 20px; box-sizing: content-box; cursor: pointer; background-color: #ccc; transition: .4s; } .slider:checked::before { transform: translateX(20px); } .slider:checked { background-color: #00a0d8; } .slider:hover { outline: 4px solid #00a0d8; } .slider:active { opacity: 0.5; } #WBOptions input[type=number] { width: 60px; border: none; border-radius: 5px; background: transparent; outline: 2px solid #00a0d8; color: var(--text1) !important; }`} GM_addStyle(styles.common) // 设置选项功能 const options = document.body.appendChild(document.createElement('div')) options.id = 'WBOptions' options.innerHTML =`<button id="WBOptionsClose">×</button> <header>⚙️宽屏选项</header> <label><input type="checkbox" class="slider"${GM_getValue('导航栏下置', true) ? ' checked': ''}>导航栏下置</label> <label><input type="number" placeholder="px" min="0" value="${GM_getValue('左右边距', 30)}">左右边距</label>` // 调出设置选项 GM_registerMenuCommand('选项', () => { options.style.display = 'grid' }) // 关闭设置选项 options.getElementsByTagName('button')[0]?.addEventListener('click', () => { options.style.display = 'none' }) for (const Element of options.children) { if (Element instanceof HTMLLabelElement) { const [input] = Element.getElementsByTagName('input') const key = Element.textContent ?? '' switch (input?.type) { case 'checkbox': input.onchange = () => { GM_setValue(key, input.checked) } break case 'number': input.oninput = () => { const val = Number(input.value) if (Number.isInteger(val)) { GM_setValue(key, val) } } break default: console.error('啊?') break } } } GM_addValueChangeListener('左右边距', (_k, _o, newVal) => { document.documentElement.style.setProperty('--layout-padding', `${newVal}px`) }) /** * @template T * @param {() => T} loaded * @returns {Promise<NonNullable<T>>} * @description 每一定时间检测某个条件是否满足,超时则reject */ const waitFor = (loaded, retry=100, interval=100) => new Promise((resolve, reject) => { const intervalID = setInterval((res = loaded()) => { if (res) { clearInterval(intervalID) return resolve(res) } if (--retry === 0) { console.error('页面加载超时') clearInterval(intervalID) return reject() } if (retry % 10 === 0) { console.debug('等待页面加载') } }, interval) }) switch ((new URL(window.location.href)).host) { case 't.bilibili.com': GM_addStyle(styles.t) console.info('使用动态样式') break case 'www.bilibili.com': { // #region 首页 if (document.getElementById('i_cecream')) { GM_addStyle(styles.home) console.info('使用首页宽屏样式') break } // #endregion // #region 阅读页 if (document.getElementsByClassName('article-detail')[0]) { GM_addStyle(styles.read) console.info('使用阅读页宽屏样式') break } // #endregion // #region 播放页 // 播放器不存在时不执行 const player = document.getElementById('bilibili-player') if (!player) { return console.info('未找到播放器,不启用宽屏模式') } // 主容器,视频播放页为#app,番剧/影视播放页为.home-container const home = document.getElementById('app') ?? document.getElementsByClassName('home-container')[0] // 播放器外容器,视频播放页为#playerWrap,番剧/影视播放页为#bilibili-player-wrap const wrap = document.getElementById('playerWrap') ?? document.getElementById('bilibili-player-wrap') // 在新版本页面,播放器存在时都应该存在 if (!wrap || !home) { return console.error( `页面加载错误:${[ wrap ? '' : '播放器外容器', home ? '' : '主容器', ].filter(Boolean).join(', ')},请检查是否为新版页面` ) } // 等待人数加载 const infos = player.getElementsByClassName('bpx-player-video-info') await waitFor(() => infos[0]) // 导航栏 (兼容Bilibili Evolved自定义顶栏,有可能延后加载) const navigation = await (async () => { const header = document.getElementById('biliMainHeader') if (header) { header.style.setProperty('height', 'initial', 'important') home.insertAdjacentElement('afterbegin', header) // bili-header__bar不可见时使用自定义顶栏 const [headerBar] = header.getElementsByClassName('bili-header__bar') if (headerBar && window.getComputedStyle(headerBar).display === 'none') { const navbar = document.getElementsByClassName('custom-navbar') return home.insertAdjacentElement('afterbegin', await waitFor(() => navbar[0])) } } return header })() // 播放器内容器 const [container] = player.getElementsByClassName('bpx-player-container') // 播放器底中部框 (用于放置弹幕框内容) const bottomCenter = ((center=player.getElementsByClassName('bpx-player-control-bottom-center')[0]) => // 番剧版使用squirtle-controller-wrap-center,但也存在bpx-player-control-bottom-center // 所以通过检测前一个元素(bpx-player-control-bottom-left)是否有子元素来判断使用哪个 center?.previousElementSibling?.hasChildNodes() ? center : player.getElementsByClassName('squirtle-controller-wrap-center')[0] )() // 弹幕框 const [danmaku] = player.getElementsByClassName('bpx-player-sending-bar') // 正常情况应该都存在 if (!navigation || !(container instanceof HTMLElement) || !bottomCenter || !danmaku) { return console.error( `页面加载错误:${[ navigation ? '' : '导航栏', container ? '' : '播放器内容器', bottomCenter ? '' : '播放器底中部框', danmaku ? '' : '弹幕框', ].filter(Boolean).join(', ')}` ) } // 改变导航栏位置,true为视频下方,false为视频上方,默认为下方 const lowerNavigation = (value=true) => { if (value) { wrap.style.removeProperty('height') navigation.insertAdjacentElement('beforebegin', wrap) } else { wrap.style.height = `calc(100vh - ${navigation.clientHeight}px)` navigation.insertAdjacentElement('afterend', wrap) } return value } lowerNavigation(GM_getValue('导航栏下置', true)) GM_addValueChangeListener('导航栏下置', (_k, _o, newVal) => {lowerNavigation(newVal)}) // 使用宽屏样式 (除非当前是小窗模式) if (container.getAttribute('data-screen') !== 'mini') { container.setAttribute('data-screen', 'web') } // 重载container的setAttribute:data-screen被设置为mini(小窗)以外的值时将其设置为web(宽屏) container.setAttribute = new Proxy(container.setAttribute, { apply: (target, thisArg, /** @type {[string, string]} */ [name, val]) => target.apply(thisArg, [name, name === 'data-screen' && val !== 'mini' ? 'web' : val]) }) // 番剧页面需要初始与退出全屏时移除#bilibili-player-wrap的class if (wrap.id === 'bilibili-player-wrap') { wrap.className = '' document.addEventListener('fullscreenchange', () => { if (document.fullscreenElement) { wrap.className = '' } }) } // 退出全屏时弹幕框移至播放器下方 document.addEventListener('fullscreenchange', () => { if (document.fullscreenElement) { bottomCenter.replaceChildren(danmaku) } }) // 移除原 宽屏/网页全屏 按钮,因为没有用了 for (const className of [ 'bpx-player-ctrl-wide', 'bpx-player-ctrl-web', 'squirtle-widescreen-wrap', 'squirtle-pagefullscreen-wrap', ]) { player.getElementsByClassName(className)[0]?.remove() } // 添加视频样式 GM_addStyle(styles.video) // 将弹幕框移至播放器下方一次 bottomCenter.replaceChildren(danmaku) // 将笔记移至主容器,不然会被视频和导航栏遮挡 const [note] = document.getElementsByClassName('note-pc') if (note) { document.body.appendChild(note) } console.info('宽屏模式成功启用') // #region 小窗 GM_addStyle(styles.mini) const miniResizer = document.createElement('div') miniResizer.className = 'bpx-player-mini-resizer' miniResizer.onmousedown = ev => { ev.stopImmediatePropagation() ev.preventDefault() /** @param {MouseEvent} ev */ const resize = ev => { container.style.width = `${container.offsetWidth + container.offsetLeft - ev.x + 1}px` } document.addEventListener('mousemove', resize) document.addEventListener('mouseup', () => document.removeEventListener('mousemove', resize), {once: true}) } // 小窗模式下添加拖动调整大小的部件,若直接添加失败则通过MutationObserver监听添加 if (!container.getElementsByClassName('bpx-player-mini-warp')[0]?.appendChild(miniResizer)) { const [videoArea] = container.getElementsByClassName('bpx-player-video-area') if (!videoArea) { return } new MutationObserver((mutations, observer) => { for (const mutation of mutations) { if (mutation.type === 'childList') { for (const node of mutation.addedNodes) { if (node instanceof Element && node.classList.contains('bpx-player-mini-warp')) { node.appendChild(miniResizer) observer.disconnect() break } } } } }).observe(videoArea, {childList: true}) } // #endregion break // #endregion } default: console.info('未知页面') break } })()
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址