// ==UserScript== // @name B站|bilibili 分P视频详情页优化 // @license MIT // @namespace https://sumver.cn // @version 1.1.7 // @description 调整bilibili 分P视频合集列表,使得可以根据窗口大小上下铺满,标题显示得更长;适配了宽屏显示;支持小窗大小设置;以及一些其他的调整 // @author lonelylizard // @match https://www.bilibili.com/video/* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant GM_addStyle // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @downloadURL none // ==/UserScript== // 添加控制菜单 // 宽屏适配开关 const menu_widescreen_status = GM_registerMenuCommand("宽屏适配开关", function() { let cur_choose = window.confirm("当前宽屏适配状态:\n" + (GM_getValue("widescreen_status") === true ? "已开启" : "已关闭")+"\n\n按【确认】修改状态,按【取消】保持设置不变\n注:只有在【视频合集宽度调整】未开启或设置为0时,宽屏模式才会生效\n设置后请手动刷新一次网页"); if(cur_choose){ if(GM_getValue("widescreen_status")){ GM_setValue("widescreen_status",false) }else{ GM_setValue("widescreen_status",true) } } }); // 小窗尺寸设置开关 const miniwin_status = GM_registerMenuCommand("小窗尺寸设置(试验)", function() { let num = window.prompt("小窗缩放倍率,在1.1~3之间是最合理的,\n推荐倍率1.6~2.0尺寸最佳\n如设置后出现问题(如误设置为100,请输入0即可消除错误尺寸") // 调整小窗大小 if(typeof(Number(num)) === 'number'){ if(num.toString().split('.').pop().length <=2){ let ori_area = document.querySelector("#bilibili-player-placeholder") let o_height = ori_area.offsetHeight let o_width = ori_area.offsetWidth let sc_height = Math.round((o_height-56)/3 *num) let sc_width = Math.round(o_width/3 *num) if(num!=0){ GM_addStyle(`@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:${sc_height}px !important; width:${sc_width}px !important; } }`); GM_addStyle(` .bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{ height:${sc_height}px !important; width:${sc_width}px !important; }`); // 保存设置 GM_setValue("mini_height",sc_height) GM_setValue("mini_width",sc_width) }else{ // 重置尺寸 GM_setValue("mini_height",0) GM_setValue("mini_width",0) // 恢复小窗 GM_addStyle(`@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:${Math.round((o_height-56)/3)}px !important; width:${Math.round((o_width-56)/3)}px !important; } }`); GM_addStyle(` .bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{ height:${Math.round((o_height-56)/3)}px !important; width:${Math.round((o_width-56)/3)}px !important; }`); } } } }); // 视频列表标题换行开关 const menu_title_wrap_status = GM_registerMenuCommand("视频列表标题换行开关(试验)", function() { let cur_choose = window.confirm("使得右侧视频合集支持标题换行显示\n当前状态:\n" + (GM_getValue("title_wrap_status") === true ? "已开启" : "已关闭")+"\n\n按【确认】修改状态,按【取消】保持设置不变\n\n设置后请手动刷新一次网页"); if(cur_choose){ if(GM_getValue("title_wrap_status")){ GM_setValue("title_wrap_status",false) }else{ GM_setValue("title_wrap_status",true) } } }); // 视频合集列表比例调整开关 const menu_area_ratio = GM_registerMenuCommand("视频合集列表宽度调整(试验)", function() { let area_ratio_prompt = window.prompt("输入0.5表示视频列表占屏幕一半,输入0.25表示占屏幕1/4,\n当前比率:\n" + (GM_getValue("area_ratio")!=0 ?GM_getValue("area_ratio"):"未开启")+"\n\n按【确认】修改状态,按【取消】\n\n如设置导致布局混乱,请输入0还原布局\n\n注意:该功能开启时,宽屏模式会自动关闭\n保持设置不变\n\n设置后请手动刷新一次网页"); if(typeof(Number(area_ratio_prompt)) === 'number'){ if(area_ratio_prompt.toString().split('.').pop().length <=2){ GM_setValue("area_ratio",area_ratio_prompt) } } }); (function() { 'use strict'; // 去除右侧广告 GM_addStyle(`#slide_ad{display:none`); GM_addStyle(`.ad-report {display:none !important;min-width:0px !important;min-height:0px !important}`); // 去除简介下广告 GM_addStyle(`#activity_vote{display:none !important}`); // 去除右下角直播窗口 GM_addStyle(`.pop-live-small-mode{display:none !important}`); // 去除右侧游戏广告卡片 GM_addStyle(`.video-page-game-card-small{display:none !important}`); // 去除视频下方的广播广告 GM_addStyle(`.reply-notice{display:none !important}`); // 让视频列表内的视频项标题显示得更多 GM_addStyle(`.base-video-sections-v1 .video-section-list .video-episode-card__info-title[data-v-10d2177a]{width:100% !important}`); var targetNode = ""; // 选择需要观察变动的节点 if(document.getElementsByClassName('video-sections-content-list')[0]){ // fn1,fn2,fn3情况共同拥有video-sections-content-list,一起监听 targetNode = document.getElementsByClassName('video-sections-content-list')[0]; }else if(document.getElementsByClassName('multi-page-v1')[0]){ // fn4情况 targetNode = document.getElementsByClassName('multi-page-v1')[0]; } // 观察器的配置(需要观察什么变动) const config = { attributes: false, // 开启监听属性 childList: true, // 开启监听子节点 subtree: true // 开启监听子节点下面的所有节点 }; // 当观察到变动时执行的回调函数 const callback = function(mutationsList, observer) { // Use traditional 'for loops' for IE 11 for(let mutation of mutationsList) { if (mutation.type === 'childList') { // console.log('子节点有变化'); if(document.querySelector(".base-video-sections-v1")){ fn1(); } if(document.querySelector(".video-sections-v1")){ fn2(); } if(document.querySelector("video-section-title")){ fn3(); } if(document.querySelector(".multi-page-v1")){ fn4() } return; } // else if (mutation.type === 'attributes') { // console.log('The ' + mutation.attributeName + ' 属性有变化'); // } } }; // 创建一个观察器实例并传入回调函数 const observer = new MutationObserver(callback); // 以上述配置开始观察目标节点 try{ observer.observe(targetNode, config); } catch(err) { // console.log("节点不存在"); } // 之后,可停止观察 // observer.disconnect(); // 针对不带封面的视频合集列表 let fn1 = function(){ if(document.querySelector(".base-video-sections-v1")){ if(document.querySelector(".video-episode-card")){ // 带分类视频和仅标题视频合集有相同的外层div,从这里区分开两种类型 if(document.querySelector(".video-section-title")){ change_right_width("fn3") change_title_wrap("fn3") fn3() }else{ change_right_width("fn1") change_title_wrap("fn1") let list_height = document.querySelector(".video-section-list").scrollHeight; let res_height = window.innerHeight; let right_content_top_heigt = document.querySelector(".base-video-sections-v1").offsetTop; let dif_height = res_height - right_content_top_heigt - 150; // 计算列表高度,如果达不到一屏就不铺满 if(!document.querySelector(".transcript-box")){ if(list_height > dif_height){ GM_addStyle(`.video-sections-content-list{height: ${dif_height}px !important;max-height:1000px !important}`); }else{ // let temp_height = list_height + 10 // GM_addStyle(`.video-sections-content-list{height: ${temp_height}px !important;max-height:1000px !important}`); // 如果高度小于一屏,同时开始换行功能,会导致高度不正确,这里修改为去除高度属性,让其自适应 GM_addStyle(`.video-sections-content-list{height: unset !important;max-height:1000px !important}`); } }else{ // 兼容脚本:在侧边显示 Bilibili 视频字幕/文稿(原始版) if(list_height > res_height){ GM_addStyle(`.video-sections-content-list{height: ${res_height-280}px !important;max-height:1000px !important}`); }else{ // let temp_height = list_height + 10 // GM_addStyle(`.video-sections-content-list{height: ${temp_height}px !important;max-height:1000px !important}`); GM_addStyle(`.video-sections-content-list{height: unset !important;max-height:1000px !important}`); } } //加宽视频列表标题 GM_addStyle(`.video-episode-card__info-title{width:100% !important}`); // 添加滑动鼠标一个浅的聚焦颜色 GM_addStyle(`.video-episode-card__info:hover{background:#DCE2E3}`); // 去除字体蓝色提醒 GM_addStyle(`.video-episode-card__info-title:hover{color:#000 !important}`); GM_addStyle(`.video-episode-card__info:hover .video-episode-card__info-title{color:#000 !important}`); } } } }; // 针对带封面的视频合集列表 let fn2 = function(){ if(document.querySelector(".video-sections-v1")){ if(document.querySelector(".video-episode-card")){ change_right_width("fn2"); change_title_wrap("fn2"); let list_height = document.querySelector(".video-section-list").scrollHeight; let res_height = window.innerHeight; var right_content_top_heigt = document.querySelector(".video-sections-v1").offsetTop; var dif_height = res_height - right_content_top_heigt -160; // 计算列表高度,如果达不到一屏就不铺满 if(!document.querySelector(".transcript-box")){ if(list_height > dif_height){ GM_addStyle(`.video-sections-content-list{height: ${dif_height}px !important;max-height:1000px !important}`); }else{ // let temp_height = list_height + 10 // GM_addStyle(`.video-sections-content-list{height: ${temp_height}px !important;max-height:1000px !important}`); GM_addStyle(`.video-sections-content-list{height: unset !important;max-height:1000px !important}`); } }else{ // 兼容脚本:在侧边显示 Bilibili 视频字幕/文稿(原始版) if(list_height > res_height){ GM_addStyle(`.video-sections-content-list{height: ${res_height-280}px !important;max-height:1000px !important}`); }else{ // let temp_height = list_height + 10 // GM_addStyle(`.video-sections-content-list{height: ${temp_height}px !important;max-height:1000px !important}`); GM_addStyle(`.video-sections-content-list{height: unset !important;max-height:1000px !important}`); } } // 添加滑动鼠标一个浅的聚焦颜色 GM_addStyle(`.video-episode-card:hover{background:#DCE2E3}`); // 去除字体蓝色提醒 GM_addStyle(`.video-episode-card__info:hover .video-episode-card__info-title{color:#000 !important}`); GM_addStyle(`.video-episode-card:hover .video-episode-card__info-title{color:#000 !important}`); } } }; // 针对带分类的视频合集列表 let fn3 = function(){ if(document.querySelector(".base-video-sections-v1")){ if(document.querySelector(".video-section-title")){ change_right_width("fn3"); let list_height = window.innerHeight; let right_content_top_heigt = document.querySelector(".base-video-sections-v1").offsetTop; let dif_height = list_height - right_content_top_heigt - 150; // 兼容脚本:在侧边显示 Bilibili 视频字幕/文稿(原始版) if(!document.querySelector(".transcript-box")){ // 默认一屏 GM_addStyle(`.video-sections-content-list{height: ${dif_height}px !important;max-height:1000px !important}`); }else{ GM_addStyle(`.video-sections-content-list{height: ${list_height-280}px !important;max-height:1000px !important}`); } // 加宽视频列表标题 GM_addStyle(`.video-episode-card__info-title{width:100% !important}`); // 分类颜色和视频标题一样,略做修改增加辨识度 GM_addStyle(`.video-section-title{background-color: #D1D8DA !important}`); // 去除分类区域奇怪的圆角 GM_addStyle(`.video-sections-content-list{border-radius: 0px !important}`); // 重设分割线 GM_addStyle(`.border-bottom-line{background:#F1F2F3 !important}`); // 添加滑动鼠标一个浅的聚焦颜色 GM_addStyle(`.video-episode-card__info:hover{background:#DCE2E3}`); // 去除字体蓝色提醒 GM_addStyle(`.video-episode-card__info-title:hover{color:#000 !important}`); GM_addStyle(`.video-episode-card:hover .video-episode-card__info-title{color:#000 !important}`); } } }; // 针对带选集(分P)的视频合集列表 let fn4 = function(){ if(document.querySelector(".multi-page-v1")){ if(document.querySelector(".cur-list")){ change_right_width("fn4"); change_title_wrap("fn4"); let res_height = window.innerHeight; let list_height = document.querySelector(".list-box").scrollHeight; let right_content_top_heigt = document.querySelector(".multi-page-v1").offsetTop; let dif_height = res_height - right_content_top_heigt - 120; // 计算列表高度,如果达不到一屏就不铺满 if(!document.querySelector(".transcript-box")){ if(list_height > dif_height){ GM_addStyle(`.cur-list {height: ${dif_height}px !important;max-height:1000px !important}`); }else{ GM_addStyle(`.cur-list {height: ${list_height}px !important;max-height:1000px !important}`); } }else{ // 兼容脚本:在侧边显示 Bilibili 视频字幕/文稿(原始版) if(list_height > res_height){ GM_addStyle(`.cur-list {height: ${res_height-280}px !important;max-height:1000px !important}`); }else{ let temp_height = list_height + 10 GM_addStyle(`.cur-list {height: ${list_height}px !important;max-height:1000px !important}`); } } // 添加滑动鼠标一个浅的聚焦颜色 GM_addStyle(`.list-box>li:hover{background:#DCE2E3 !important}`); } } }; // 宽屏适配+自定义设置比率 let change_right_width = function(source){ // 如果有自定义比率,则优先使用 if (GM_getValue("area_ratio") && GM_getValue("area_ratio")!=0){ console.log("检测到自定义比例") let body_width = document.querySelector("#app").offsetWidth; let res_width = window.innerWidth; console.log(body_width) var dif_width = Math.round(res_width*GM_getValue("area_ratio"),2); console.log(dif_width) //不同的合集页需要单独适配 if(source == "fn1"){ // 调整合集名称长度 GM_addStyle(`.first-line-left>a {max-width: ${dif_width}px !important}`); // 调整合集宽度 GM_addStyle(`.right-container {width: ${dif_width}px !important}`); GM_addStyle(`.left-container {width: max-content !important}`); GM_addStyle(`#bilibili-player {width: 100% !important;height:max-content}`); GM_addStyle(`#playerWrap {height: max-content !important}`); // 调整标题宽度 GM_addStyle(`.video-episode-card__info-title {width: 100% !important}`); } if(source == "fn2"){ // 调整合集名称长度 GM_addStyle(`.first-line-left>a {max-width: ${dif_width}px !important}`); // 调整合集宽度 GM_addStyle(`.right-container {width: ${dif_width}px !important}`); GM_addStyle(`.left-container {width: max-content !important}`); GM_addStyle(`#bilibili-player {width: 100% !important;height:max-content}`); GM_addStyle(`#playerWrap {height: max-content !important}`); //调整合集内视频标题的宽度 GM_addStyle(`.video-sections-item {width: 95% !important}`); } if(source == "fn3"){ // 调整合集名称长度 GM_addStyle(`.first-line-left>a {max-width: ${dif_width}px !important}`); // 调整合集宽度 GM_addStyle(`.right-container {width: ${dif_width}px !important}`); GM_addStyle(`.left-container {width: max-content !important}`); GM_addStyle(`#bilibili-player {width: 100% !important;height:max-content}`); GM_addStyle(`#playerWrap {height: max-content !important}`); // 调整标题宽度 GM_addStyle(`.video-episode-card__info-title {width: 100% !important}`); } if(source == "fn4"){ //分P视频无需调整标题宽度,因为选集名称固定为“视频选集” // 调整合集宽度 GM_addStyle(`.right-container {width: ${dif_width}px !important}`); GM_addStyle(`.left-container {width: max-content !important}`); GM_addStyle(`#bilibili-player {width: 100% !important;height:max-content}`); GM_addStyle(`#playerWrap {height: max-content !important}`); // 合集内需要单独调整 GM_addStyle(`#multi_page .cur-list .list-box>li {width: ${dif_width}px}`); // 分P视频合集的分P时长偏右,微调 GM_addStyle(`.cur-list>ul>li>a{margin-right: 15px !important}`); } }else if(GM_getValue("widescreen_status")){ // console.log("检测到开启了宽屏") let body_width = document.querySelector("#app").offsetWidth; let res_width = window.innerWidth; if(res_width-100 > body_width){ //带鱼屏 let left_div = document.querySelector(".left-container").offsetWidth; let right_div = document.querySelector(".right-container").offsetWidth; var dif_width = (body_width - (left_div+right_div))+right_div-100; // GM_addStyle(`.right-container {width: ${dif_width}px !important}`); }else{ //非带鱼屏 let left_div = document.querySelector(".left-container").offsetWidth; let right_div = document.querySelector(".right-container").offsetWidth; var dif_width = (res_width - (left_div+right_div))+right_div-80; // GM_addStyle(`.right-container {width: ${dif_width}px !important}`); } //不同的合集页需要单独适配 if(source == "fn1"){ // 调整合集名称长度 GM_addStyle(`.first-line-left>a {max-width: ${dif_width-200}px !important}`); // 调整合集宽度 GM_addStyle(`.right-container {width: ${dif_width}px !important}`); // 调整标题宽度 GM_addStyle(`.video-episode-card__info-title {width: 100% !important}`); } if(source == "fn2"){ // 调整合集名称长度 GM_addStyle(`.first-line-left>a {max-width: ${dif_width-200}px !important}`); // 调整合集宽度 GM_addStyle(`.right-container {width: ${dif_width}px !important}`); //调整合集内视频标题的宽度 GM_addStyle(`.video-sections-item {width: 95% !important}`); } if(source == "fn3"){ // 调整合集名称长度 GM_addStyle(`.first-line-left>a {max-width: ${dif_width-200}px !important}`); // 调整合集宽度 GM_addStyle(`.right-container {width: ${dif_width}px !important}`); } if(source == "fn4"){ //分P视频无需调整标题宽度,因为选集名称固定为“视频选集” // 调整合集宽度 GM_addStyle(`.right-container {width: ${dif_width}px !important}`); // 合集内需要单独调整 GM_addStyle(`#multi_page .cur-list .list-box>li {width: ${dif_width}px}`); // 分P视频合集的分P时长偏右,微调 GM_addStyle(`.cur-list>ul>li>a{margin-right: 15px !important}`); } } } // 视频合集换行功能,不限制标题行数 let change_title_wrap = function(source){ if(GM_getValue("title_wrap_status")){ if(source=="fn1"){ GM_addStyle(`.base-video-sections-v1 .video-section-list .video-episode-card__info-title{white-space:normal !important;flex-wrap:wrap !important;max-height:300px !important}`); GM_addStyle(`.base-video-sections-v1 .video-section-list .video-episode-card{height:100% !important}`); // 因为换行会改变整体高度,这里需要重写高度 GM_addStyle(`.video-section-list{height:100% !important}`); GM_addStyle(`.video-episode-card__info{height:100% !important}`); // 换行后会导致视频列表项不明显,这里加宽了项之间的间距 GM_addStyle(`.video-episode-card__info{margin-bottom:6px !important}`); } if(source=="fn2"){ //不处理,因为默认支持2行,足够显示长标题 } if(source=="fn3"){ GM_addStyle(".video-episode-card__info-title{white-space:normal !important;max-height:unset !important}") GM_addStyle(".base-video-sections-v1 .video-section-list .video-episode-card__info{height:unset !important}") GM_addStyle(".base-video-sections-v1 .video-section-list .video-episode-card{height:unset !important}") //todo:现在这么设置意味着收起分类功能会失效,但是想着全展开也没啥不好的,暂时不做修复 GM_addStyle(".video-section-list{height:100% !important}") // 换行后会导致视频列表项不明显,这里加宽了项之间的间距 GM_addStyle(`.video-episode-card{margin-bottom:6px !important}`); } if(source=="fn4"){ GM_addStyle(`.multi-page-v1 .cur-list .list-box li{white-space:normal !important;height:unset !important;}`); // // 换行后会导致视频列表项不明显,这里缩小标题文字换行间距 GM_addStyle(`.part{line-height:normal !important}`) } } } // 窗口大小变化时调整合集列表大小 const getWindowInfo = () => { fn1(); fn2(); fn3(); fn4(); }; const debounce = (fn, delay) => { let timer; return function() { if (timer) { clearTimeout(timer); } timer = setTimeout(() => { fn(); }, delay); } }; const cancalDebounce = debounce(getWindowInfo, 500); window.addEventListener('resize', cancalDebounce); fn1(); fn2(); fn3(); fn4(); if(GM_getValue("mini_height") != 0 ){ GM_addStyle(`@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_height")}px !important; width:${GM_getValue("mini_width")}px !important; } }`); GM_addStyle(` .bpx-player-container[data-revision="1"][data-screen=mini], .bpx-player-container[data-revision="2"][data-screen=mini]{ height:${GM_getValue("mini_height")}px !important; width:${GM_getValue("mini_width")}px !important; }`); } window.addEventListener('pushState', function(e) { fn1(); fn2(); fn3(); fn4(); }); window.addEventListener('replaceState', function(e) { fn1(); fn2(); fn3(); fn4(); }); // 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) { fn1(); fn2(); fn3(); fn4(); }; })();