B站|bilibili 小窗调整|优化

bilibili网页版划到评论区时出现的小窗,该脚本可以自由调整小窗的尺寸,并且可以以真实的视频比例展示(而不会出现大黑边,尤其是竖屏视频)

// ==UserScript==
// @name         B站|bilibili 小窗调整|优化
// @license      MIT
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAyZJREFUaEPtWlFy2jAQ3XXof5pewJkpmekpAidJ+IQeAnKIwifkJDin6EzoTNwDlOYA4O2sVIEsFFuSkQdm8CfI0r6VdvftkxHO/MEQ+7/8eH3cJtvsffgtD3nf9s71bNV7H3Yz3/m8AdzMVmMgmPBCBW5um4K4nv1MkTpzBOgBwmQ97D75gPAHMH19A8BULdIEBBufUOdtbzDl69HdbVQActGrZVMQh8bzjkLf9xh57wB7xwYCiQZ/vt8tXLx3LON5rSAATUBwsCYESx1oiOfV+8EAQkAcGk95gTjwPTY6+AMAYhHAByJKEWgXrNVHYx/Uchx9kF7NcXIsAdamY0TICtg8m1mvBODzdLUU6eyEHzPWdgDOwfidX7V6IQDoxemEnV827T8ItKW0cwHBRRQ/8j6fNeY7pwGmkyZEc714ihpANMCb2a85ED2WDfUv6bGB2uoHIC7QGrwBpCo2ABGr0xXp6xBAdgHQhufVGpcdqPK2T5fGqRugkwJscp+G6Gg7wMYKFpMk90BFT6U3V0qtp24ORJESBdeBlypQwQBEsYNPY91Y624gLtbDr4O6uKiv/JLgEW4G+g41A1Bq/ewmsjf/jrr9OgCuvGs96pbIZjAAmYPLvXDJSMQF02Is6LdLVyYpO9wTQU9SdjvNNvvjZgBExS56gEmGRfGyTZjD+wVh1c4cgBLHsaxQNAJQdyza+P8CoA0vV61x2YGQHeCi55KZXOaOvgMmnVAFS5cfFY0IkVKiAmDjCXEu6gHBk6QZWqOEMOE6IceECcNRAezFATZaFSbKuW6YFMSVM5nHKjoAXlAVJPa2ukNQvwnPW8Qpl/N/6chcvRRzXCtHqE0AImFYZRVHXh/TWHNuqwDHmW2f/kqCRV7gtu/T7sUGY22CGEAV1xe6C9ZL37GNl1K/qZpL8e38xV3lPbvEGNu3YfPrrWu557TqpGGLxHrL7LutV0xIMG73poavpA77YiW5sDM4FgugZ5MEOl3yWZVhOJ6Cbc2EjgKzEwBbpmpyNWo7Xqbq4foFgDMARdSuCkqP/aGHnJvFs86DTgJd4sgLgMuEbY/5B0Ybna/xpe4TAAAAAElFTkSuQmCC
// @namespace    https://sumver.cn
// @version      0.0.1
// @description  bilibili网页版划到评论区时出现的小窗,该脚本可以自由调整小窗的尺寸,并且可以以真实的视频比例展示(而不会出现大黑边,尤其是竖屏视频)
// @match        https://www.bilibili.com/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-end
// ==/UserScript==

// 样式处理
const setStyle = function (css) {
	let css_list = css.split("}")
	css_list.forEach((item, index, array) => {
		GM_addStyle(item + "}")
	});
}


// 小窗尺寸设置开关
const miniwin_status = GM_registerMenuCommand("小窗尺寸设置", function () {
	let num = window.prompt("小窗缩放倍率,在1.1~3之间是最合理的,\n推荐倍率1.6~2.0尺寸最佳\n如设置后出现问题,请输入0即可恢复预设尺寸")
	// 调整小窗大小
	if (typeof (Number(num)) === 'number') {
		if (num.toString()
			.split('.')
			.pop()
			.length <= 2) {

			let ori_area = document.querySelector("#bilibili-player-placeholder")
			// 原始小窗:360* 203
			let o_height = 203
			let o_width = 360
			let sc_height = Math.round(o_height * num, 2)
			let sc_width = Math.round(o_width * num, 2)
			if (num != 0) {
				// 横屏视频
				if (video_obj[0] > video_obj[1]) {
					let css = `
							@media screen and (min-width: 1681px){
								.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
									height:unset !important;
									width:${sc_width}px !important;
								}
								.bpx-player-video-perch, .bpx-player-video-area, .bpx-player-video-wrap{
									height:inherit !important;
									width:inherit !important;
								}
							}
							.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
								height:unset !important;
								width:${sc_width}px !important;
							}
							.bpx-player-video-perch, .bpx-player-video-area, .bpx-player-video-wrap{
								height:inherit !important;
								width:inherit !important;
							}`
					setStyle(css)
				} else {
					// 竖屏视频
					let css = `
							@media screen and (min-width: 1681px){
							.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
								height:unset !important;
								width:${sc_height}px !important;
							}
							.bpx-player-video-perch, .bpx-player-video-area, .bpx-player-video-wrap{
								height:inherit !important;
								width:inherit !important;
							}
						}
						.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
							height:unset !important;
							width:${sc_height}px !important;
						}
						.bpx-player-video-perch, .bpx-player-video-area, .bpx-player-video-wrap{
							height:inherit !important;
							width:inherit !important;
						}`
					setStyle(css)
				}

				// 保存设置
				GM_setValue("mini_height", sc_height)
				GM_setValue("mini_width", sc_width)
			} else {
				// 重置尺寸
				GM_setValue("mini_height",324)
                GM_setValue("mini_width",576) 
				// 恢复小窗
				if (video_obj[0] > video_obj[1]) {
					let css = `
							@media screen and (min-width: 1681px){
								.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
									height:unset !important;
									width:${GM_getValue("mini_width")}px !important;
								}
								.bpx-player-video-perch, .bpx-player-video-area, .bpx-player-video-wrap{
									height:inherit !important;
									width:inherit !important;
								}
							}
							.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
								height:unset !important;
								width:${GM_getValue("mini_width")}px !important;
							}
							.bpx-player-video-perch, .bpx-player-video-area, .bpx-player-video-wrap{
								height:inherit !important;
								width:inherit !important;
							}`
					setStyle(css)
				} else {
					// 竖屏视频
					let css = `
							@media screen and (min-width: 1681px){
							.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
								height:unset !important;
								width:${GM_getValue("mini_height")}px !important;
							}
							.bpx-player-video-perch, .bpx-player-video-area, .bpx-player-video-wrap{
								height:inherit !important;
								width:inherit !important;
							}
						}
						.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
							height:unset !important;
							width:${GM_getValue("mini_height")}px !important;
						}
						.bpx-player-video-perch, .bpx-player-video-area, .bpx-player-video-wrap{
							height:inherit !important;
							width:inherit !important;
						}`
					setStyle(css)
				}
			}
		}
	}
});


(function () {
    'use strict';

    // 第一次使用则给默认设置
    if (!GM_getValue("mini_height")) {
        GM_setValue("mini_height",324)
        GM_setValue("mini_width",576) 
    }

    let wait_fn = function () {
        function waitForElement(selector, timeout = 8000) {
            return new Promise((resolve, reject) => {
                const startTime = Date.now();
                const checkInterval = setInterval(() => {
                    const element = document.querySelector(selector);
                    if (element) {
                        clearInterval(checkInterval);
                        resolve(element);
                    } else if (Date.now() - startTime > timeout) {
                        clearInterval(checkInterval);
                        reject(new Error('没找到video标签'));
                    }
                }, 100);
            });
        }
    
        waitForElement('video', 8000)
            .then(element => {
                // console.log("找到了video标签")
                mini_win_fn()
            })
            .catch(error => {
                  console.error(error);
            });
    }
    

	// 小窗处理函数
	const mini_win_fn = function () {
		// 初始化小窗大小
		// 处理横屏、竖屏小窗
		let video = document.querySelector('video')

		video.addEventListener('canplay', function (e) {
			window.video_obj = [e.target.videoWidth, e.target.videoHeight]
			if (GM_getValue("mini_height") != 0) {
				if (video_obj[0] > video_obj[1]) {
					let css =
						`@media screen and (min-width: 1681px){
								.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
									height:unset !important;
									width:${GM_getValue("mini_width")}px !important;
									}
								/* 这里需要使用继承inherit,否则小窗显示内容、主体视频播放器尺寸都会异常 */
								.bpx-player-video-perch, .bpx-player-video-area, .bpx-player-video-wrap{
									height:inherit !important;
									width:inherit !important;
									}
								}
								.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
									height:unset !important;
									width:${GM_getValue("mini_width")}px !important;
								}`
					setStyle(css)
				} else {
					let css =
						`@media screen and (min-width: 1681px){
								.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
									height:${GM_getValue("mini_width")}px !important;
									width:unset !important;
									}
								/* 这里需要使用继承inherit,否则小窗显示内容、主体视频播放器尺寸都会异常 */
								.bpx-player-video-perch, .bpx-player-video-area, .bpx-player-video-wrap{
									height:inherit !important;
									width:inherit !important;
									}
								}
								.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
									height:${GM_getValue("mini_width")}px !important;
									width:unset !important;
								}`
					setStyle(css)
				}
			} else if (typeof (GM_getValue("mini_height")) == 'undefined' || GM_getValue("mini_height") == 0) {
				// 小窗默认比例 360*203
				let o_height = 203
				let o_width = 360
				let css =
					`@media screen and (min-width: 1681px){
									.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
										height:${o_height}px !important;
										width:${o_width}px !important;
										}
									/* 这里需要使用继承inherit,否则小窗显示内容、主体视频播放器尺寸都会异常 */
									.bpx-player-video-perch, .bpx-player-video-area, .bpx-player-video-wrap{
										height:inherit !important;
										width:inherit !important;
										}
									}
									/* 恢复到小窗默认尺寸 */
									.bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{
										height:${o_height}px !important;
										width:${o_width}px !important;
									}`
				setStyle(css)
			}
		})


	}


	// 统一调用入口
	let run = function () {
		wait_fn()
    }
	run()

	window.addEventListener('pushState', function (e) {
		run()
	});

	window.addEventListener('replaceState', function (e) {
		run()
	});

	// B站视频详情页的自动播放下一个视频,或者点击其他视频,使用的是pushState不会刷新页面,这里需要重写pushState、replaceState为来实现监听页面视频是否切换
	const bindEventListener = function (type) {
		const historyEvent = history[type];
		return function () {
			const newEvent = historyEvent.apply(this, arguments);
			const e = new Event(type);
			e.arguments = arguments;
			window.dispatchEvent(e);
			return newEvent;
		};
	};
	history.pushState = bindEventListener('pushState');
	history.replaceState = bindEventListener('replaceState');

	// 浏览器前进、后退时,重新计算
	window.onpopstate = function (event) {
		run()
	};

})();