Greasy Fork

Greasy Fork is available in English.

B站|bilibili 分P视频详情页优化

调整bilibili 网页版视频详情页右侧的分P视频合集列表(带封面的视频合集、带选集视频合集、仅标题视频合集、带分类的视频合集),使得可以根据窗口大小上下铺满,并且标题显示得更长(如果是宽屏,支持显示超长标题);去除几处广告;去除页面右侧底部的直播banner位

当前为 2024-04-08 提交的版本,查看 最新版本

// ==UserScript==
// @name         B站|bilibili 分P视频详情页优化
// @license      MIT
// @namespace    https://sumver.cn
// @version      1.0.9
// @description  调整bilibili 网页版视频详情页右侧的分P视频合集列表(带封面的视频合集、带选集视频合集、仅标题视频合集、带分类的视频合集),使得可以根据窗口大小上下铺满,并且标题显示得更长(如果是宽屏,支持显示超长标题);去除几处广告;去除页面右侧底部的直播banner位
// @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
// @run-at       document-end
// ==/UserScript==

// 添加控制菜单
const menu_widescreen_status = GM_registerMenuCommand("宽屏适配开关(试验)", function() {
    let cur_choose = window.confirm("当前宽屏适配状态:\n" + (GM_getValue("widescreen_status") === true ? "已开启" : "已关闭")+"\n\n按【确认】修改状态,按【取消】保持设置不变\n\n设置后请手动刷新一次网页");
    if(cur_choose){
        if(GM_getValue("widescreen_status")){
            GM_setValue("widescreen_status",false)
        }else{
            GM_setValue("widescreen_status",true)
        }
    }
  });

(function() {
    'use strict';

    // 去除右侧广告
    GM_addStyle(`#slide_ad{display:none`);
    GM_addStyle(`.ad-report[data-v-e79faaca] {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(`.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")){

                change_right_width("fn1")

                // 带分类视频和仅标题视频合集有相同的外层div,从这里区分开两种类型
                if(document.querySelector(".video-section-title")){
                    fn3()
                }else{
                    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(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}`);
                    }
                }

            }
        }
    };

    // 针对带封面的视频合集列表
    let fn2 = function(){
        if(document.querySelector(".video-sections-v1")){
            if(document.querySelector(".video-episode-card")){

                change_right_width("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(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}`);
                }
            }
        }
    };

    // 针对带分类的视频合集列表
    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;

                // 默认一屏
                GM_addStyle(`.video-sections-content-list{height: ${dif_height}px !important;max-height:1000px !important}`);

                // 分类颜色和视频标题一样,略做修改增加辨识度
                GM_addStyle(`.video-section-title{background-color: bisque !important`);

            }
        }
    };

    // 针对带选集(分P)的视频合集列表
    let fn4 = function(){
        if(document.querySelector(".multi-page-v1")){
            if(document.querySelector(".cur-list")){

                change_right_width("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(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}`);
                }
        }   }
    };

    // 宽屏适配
    let change_right_width = function(source){

        if(GM_getValue("widescreen_status")){
            let body_width = document.querySelector("#app").offsetWidth;        let res_width = window.innerWidth;

            if(res_width-100 > body_width){
                //带鱼屏
                console.log("带鱼屏")
                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{
                //非带鱼屏
                console.log("非带鱼屏")
                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}`);
        }
        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}`);
        }
        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(`.multi-page-v1.small-mode .cur-list .list-box li {width: ${dif_width}px !important}`);
            // 分P视频合集的分P时长偏右,微调
            GM_addStyle(`#multi_page{margin-right: -15px}`);

        }
        }
    }

    // 窗口大小变化时调整合集列表大小
    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();

    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();
    };

})();