Greasy Fork

Greasy Fork is available in English.

仰晨-B站改造计划(为了学习版)

1、《不用长按就可以3倍速啦 支持 2.5 3 3.5 4 倍速(2022.11.15》 2、《给出每集剩下的时间-----《只有教程集合才有效》 鬼畜集合的标签是不同的所以无效的,有时候集合也会加载太快导致失败,第二次有了缓存基本就行了,暂时就不改了,我要学习java 55555 js我就是个小白,算是想要优化一下看教程 又觉得自己应该可以 就百度 来完成了(2023.1.18》3、《添加按钮控制《看进度》是否打开2023.1.20》4、《增加显示总时长2023.1.20 02:15》5、《改变总时长位置,增加按钮滚到当前视频集到屏幕 样式分离开来 2023.1.25》6、《优化不是集合就不执行,添加一个提前加载按钮,修复之前倍数添加变蓝bug2023.1.30 ---.31添加过渡效果、添加非集合提示+动画效果》

当前为 2023-08-21 提交的版本,查看 最新版本

// ==UserScript==
// @name         仰晨-B站改造计划(为了学习版)
// @description  1、《不用长按就可以3倍速啦   支持 2.5    3   3.5    4 倍速(2022.11.15》    2、《给出每集剩下的时间-----《只有教程集合才有效》 鬼畜集合的标签是不同的所以无效的,有时候集合也会加载太快导致失败,第二次有了缓存基本就行了,暂时就不改了,我要学习java 55555 js我就是个小白,算是想要优化一下看教程  又觉得自己应该可以 就百度 来完成了(2023.1.18》3、《添加按钮控制《看进度》是否打开2023.1.20》4、《增加显示总时长2023.1.20 02:15》5、《改变总时长位置,增加按钮滚到当前视频集到屏幕 样式分离开来 2023.1.25》6、《优化不是集合就不执行,添加一个提前加载按钮,修复之前倍数添加变蓝bug2023.1.30 ---.31添加过渡效果、添加非集合提示+动画效果》
// @license      AGPL License
// @namespace    https://mp.weixin.qq.com/s/zsVmSmd63OIxuoDbKGA-xg
// @version      2023.8.21
// @author       仰晨
// @match        *://www.bilibili.com/video/*
// @icon         https://bilibili.com/favicon.ico
// @grant        none
// ==/UserScript==


/**
 * 创建一个带属性的 HTML 元素***************************************************************************************************************************2023.7.10_01:18
 * @param {Object} options - 参数对象。
 * @param {string} options.type - HTML 元素的类型。
 * @param {Object} options.attributes - 元素的属性键值对。
 * @param {string} [options.textContent] - 可选的元素文本内容。
 * @return {HTMLElement} 带有指定属性的新 HTML 元素。
 */
function createElement({ type, attributes, textContent }) {
  const element = document.createElement(type);
  // 使用对象解构将属性键值对添加到元素
  Object.entries(attributes).forEach(([key, value]) => element.setAttribute(key, value));
  // 如果提供了 textContent 参数,则设置元素的文本内容
  if (textContent)element.innerText = textContent;
  return element;
}




/**
 * 格式化总时长,将秒数转换为小时、分钟和秒的字符串表示形式。*********************************************************************************************2023.7.10_01:18
 *
 * @param {number} totalSeconds - 总时长(单位:秒)。
 * @return {string} 格式化的总时长字符串,包含小时、分钟和秒。
 */
function formatDuration(totalSeconds) {
  const hours = parseInt(totalSeconds / 60 / 60);
  const minutes = parseInt((totalSeconds / 60) % 60);
  const seconds = parseInt(totalSeconds % 60);

  const hoursStr = hours > 0 ? `${hours}小时` : '';
  const minutesStr = minutes > 0 ? `${minutes}分` : '';

  return `${hoursStr}${minutesStr}${seconds}秒"`;
}







function 倍速 () {
    function 插入倍速 (速度){
        //创建一个li元素
        const para = createElement({type: 'li',
                                    attributes: {class: 'bpx-player-ctrl-playbackrate-menu-item','data-value': 速度},
                                    textContent: 速度+"x"});
        //获取父标签
        let div=document.getElementsByClassName("bpx-player-ctrl-playbackrate-menu")[0];
        //添加标签
        let one=div.firstChild;// 获取父标签的第一个子元素
        div.insertBefore(para,one); // 在父标签的第一个子元素,前插入div标签
    }
    插入倍速(2.5);
    插入倍速(3);
    插入倍速(3.5);
    插入倍速(4);
}




//未解决问题 尝试按钮点太快可能会导致网页崩溃 (2023.2.8 尝试延迟2秒再出现)
var flag = true;//如果点了尝试 页面加载完成就不用再执行了

setTimeout(function (){
    //创建一个“尝试”按钮
    const try_button = createElement({type: 'div',
                                      attributes: {id: 'setText',title: '只能点一次,确定加载好了再点'},
                                      textContent: '尝试提前加载'});

    document.getElementsByTagName("body")[0].appendChild(try_button);
    try_button.onclick=function () {
        document.getElementById("setText").remove();//成功加载把“尝试”先删了
        show ();
        倍速();
    }
},2000)


window.scrollBy(0/*左右*/, 100/*上下*/); //让视频在滚到顶部栏下方2023.8.21



/*
 *     |\_
 *   -' | `.
 *  /7      `-._
 * /            `-.____________
 * \-'_                        `-._
 *  -- `-._                    |` -`.
 *        |\               \   |   `\\
 *        | \  \______...---\_  \    \\
 *        |  \  \           | \  |    ``-.__--.
 *        |  |\  \         / / | |       ``---'
 *      _/  /_/  /      __/ / _| |
 *     (,__/(,__/      (,__/ (,__/
 *
 */

window.onload=function() {

    //可能点按钮的时候视频还没加载好所以要再判断一下
    if (document.getElementsByClassName("bpx-player-ctrl-playbackrate-menu-item").length===6) {
        倍速();
    }
    if (flag){
        document.getElementById("setText").remove();//成功加载把“尝试”先删了
        show ();
    }
    //删除搜索框推荐的诱惑2023.2.25----27删除变修改(有时删除不掉)
    let search =document.getElementsByClassName("nav-search-input")[0];
    search.setAttribute("placeholder","好好学习");
    search.setAttribute("title","天天向上");

}//加载完成执行—收括号----------------------------------




//看进度方法---看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看


//------------给出每集剩下的时间-----《只有教程集合才有效》 鬼畜集合的标签是不同的所以无效的-------------------------=======================================================
function lookJinDu(){
    const element = document.getElementById("multi_page").getElementsByClassName("duration");	//每一集是时间标签

    const allElement = document.getElementsByClassName("list-box")[0].children;		//视频集合下的全部标签

    console.log("视频列表共有"+element.length);
    if(element.length===allElement.length){				//如果还没有进度就加进度
        //定义一个数组放每个视频的秒数
        let arr = [];
        let s_all = 0;
        //收集总时长-----//单纯是秒更好处理---------------------------------
        for(let i=0;i<element.length;i++){
            let timeStr = element[i].innerHTML;
            let s =0;//记录本次秒
            //console.log(timeStr);
            let times=timeStr.split(":");
            //console.log(times);
            if(times.length===2){
                s=parseInt(times[0])*60 + parseInt(times[1]);
            }else if(times.length===3){
                s = parseInt(times[0]) * 60 * 60 + parseInt(times[1]) * 60 + parseInt(times[2]);
            }else{
                s=parseInt(times[0]);
            }
            s_all+=s;
            arr.push(s);//将一个或多个元素添加到数组的末尾,并返回数组的新长度。
        }
        console.log("全部变成秒为"+s_all);


        //显示总时长在最前面2023.1.20  02:04 begin
        {//放在循环里面防止变量冲突
            let para = createElement({type: 'div',
                                      attributes: {class: 'jindu',
                                                   style:"position: absolute;top: -1px;left: 22%;color: #f2bfbf;"},
                                      textContent:`总时长:${formatDuration(s_all)}  加油ヾ(◍°∇°◍)ノ゙"`});
            

            let list=document.getElementsByClassName("list-box")[0];//获取父标签---列表
            let listIndex=list.getElementsByTagName("li")[0];// 获取父标签的第1个子元素
            list.insertBefore(para,listIndex); // 在父标签的第一个子元素,前插入div标签
        }


        let s_front = 0;		//遍历到的时间总和
        //对每个 进行处理------------------------------------------------------------------------------------
        for(let i=0;i<arr.length;i++){
            s_front+=arr[i];
            //console.log("进度:"+(s_front/s_all*100).toFixed(2)+"%")

            //转换为时分秒---------输出才用  内部用秒就好
            let H=0;
            let m=0;
            let s=0;

            //剩下时间
            s=s_all-s_front;

            m=parseInt(s/60);
            s=s%60;

            H=parseInt(m/60);
            m=m%60;
            //console.log("剩下时间:"+H+"小时"+m+"分"+s+"秒")

            //展示阶段-------------------------------------------------------------------
            //创建一个div标签
            let para = createElement({type: 'div',
                                      attributes: {class: 'jindu'},
                                      textContent: `看完${i + 1}集后  剩下时间:${H}小时${m}分${s}秒  进度:${(s_front / s_all * 100).toFixed(2)}%`});
            document.getElementsByClassName("clickitem")[i].appendChild(para);//2023.4.20放在列表下 再考虑用css解决  2023.5.4router-link-active有时候会不存在换他子类
        }
        document.getElementById("setText").innerText="已打开看进度";
    }else{//删除存在的进度标签
        let jindu = document.getElementsByClassName("jindu");
        for (let i = jindu.length-1; i>=0;i--)jindu[i].remove();
        
        document.getElementById("setText").innerText="已关闭看进度";
    }
}//看进度方法结束-----------------看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`   `4!!!!!!!!!!~4!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   <~:   ~!!!~   ..  4!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  ~~~~~~~  '  ud$$$$$  !!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  ~~~~~~~~~: ?$$$$$$$$$  !!!!!!!!!!!!!!
// !!!!!!!!!!!`     ``~!!!!!!!!!!!!!!  ~~~~~          "*$$$$$k `!!!!!!!!!!!!!
// !!!!!!!!!!  $$$$$bu.  '~!~`     .  '~~~~      :~~~~          `4!!!!!!!!!!!
// !!!!!!!!!  $$$$$$$$$$$c  .zW$$$$$E ~~~~      ~~~~~~~~  ~~~~~:  '!!!!!!!!!!
// !!!!!!!!! d$$$$$$$$$$$$$$$$$$$$$$E ~~~~~    '~~~~~~~~    ~~~~~  !!!!!!!!!!
// !!!!!!!!> 9$$$$$$$$$$$$$$$$$$$$$$$ '~~~~~~~ '~~~~~~~~     ~~~~  !!!!!!!!!!
// !!!!!!!!> $$$$$$$$$$$$$$$$$$$$$$$$b   ~~~    '~~~~~~~     '~~~ '!!!!!!!!!!
// !!!!!!!!> $$$$$$$$$$$$$$$$$$$$$$$$$$$cuuue$$N.   ~        ~~~  !!!!!!!!!!!
// !!!!!!!!! **$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$Ne  ~~~~~~~~  `!!!!!!!!!!!
// !!!!!!!!!  J$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$N  ~~~~~  zL '!!!!!!!!!!
// !!!!!!!!  d$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$c     z$$$c `!!!!!!!!!
// !!!!!!!> <$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$> 4!!!!!!!!
// !!!!!!!  $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$  !!!!!!!!
// !!!!!!! <$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*"   ....:!!
// !!!!!!~ 9$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$e@$N '!!!!!!!
// !!!!!!  9$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$  !!!!!!!
// !!!!!!  $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$""$$$$$$$$$$$~ ~~4!!!!
// !!!!!!  9$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$    $$$$$$$Lue  :::!!!!
// !!!!!!> 9$$$$$$$$$$$$" '$$$$$$$$$$$$$$$$$$$$$$$$$$$    $$$$$$$$$$  !!!!!!!
// !!!!!!! '$$*$$$$$$$$E   '$$$$$$$$$$$$$$$$$$$$$$$$$$$u.@$$$$$$$$$E '!!!!!!!
// !!!!~`   .eeW$$$$$$$$   :$$$$$$$$$$$$$***$$$$$$$$$$$$$$$$$$$$u.    `~!!!!!
// !!> .:!h '$$$$$$$$$$$$ed$$$$$$$$$$$$Fz$$b $$$$$$$$$$$$$$$$$$$$$F '!h.  !!!
// !!!!!!!!L '$**$$$$$$$$$$$$$$$$$$$$$$ *$$$ $$$$$$$$$$$$$$$$$$$$F  !!!!!!!!!
// !!!!!!!!!   d$$$$$$$$$$$$$$$$$$$$$$$$buud$$$$$$$$$$$$$$$$$$$$"  !!!!!!!!!!
// !!!!!!! .<!  #$$*"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*  :!!!!!!!!!!!
// !!!!!!!!!!!!:   d$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$#  :!!!!!!!!!!!!!
// !!!!!!!!!!!~  :  '#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*"    !!!!!!!!!!!!!!!
// !!!!!!!!!!  !!!!!:   ^"**$$$$$$$$$$$$$$$$$$$$**#"     .:<!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!:...                      .::!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

//页面添加元素方法+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++2023.1.30抽取出来+++++++
function show (){
    //————————————————看进度按钮开关——————————————————————————————
    if (flag) {//这个按钮不存在????????????????
        console.log("---开始创建按钮看进度按钮开关---");
        flag=false;
        if (document.querySelector(".head-left h3") != null) {//视频选集存在??????????????????????
            //创建一个按钮
            let bt = createElement({type: 'div',
                                    attributes: {id: 'setText'}, //设置id 方便改内容
                                    textContent: `已打开看进度`});

            //插入父标签下
            document.getElementById("app").appendChild(bt);

            bt.onclick = function () {
                lookJinDu();
            };//开关按钮

            lookJinDu();//默认打开

            //——————————————————————————————————————————————————————
            //滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚—集合中《当前在看的》 滚到屏幕可见位置—滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚

            //创建一个按钮
            let see = createElement({type: 'div',
                                    attributes: {id: 'see',
                                                title:"如果正在播放的在屏幕可见处。\n是不会有效果的"},
                                    textContent: `当前播放集`});

            //插入父标签下
            document.getElementsByClassName("head-con")[0].appendChild(see);

            see.onclick = function () {
                //有时class会变...
                let on = document.getElementsByClassName("on");
                if (on < 2) {
                    document.getElementsByClassName("watched")[0].scrollIntoView({block: "nearest",behavior: "smooth"});
                } else {
                    on[on.length - 1].scrollIntoView({block: "nearest", behavior: "smooth"});
                }//平滑滚到到屏幕可见---滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚滚/滚/滚/滚/滚/
            }
        } else {//视频选集不存在??????????????????????2023.1.30
            //创建一个提醒按钮
            let tis = createElement({type: 'div',
                                    attributes: {id: 'setText'},
                                    textContent: `记得好好学习`});


            //插入父标签下
            document.getElementById("app").appendChild(tis);
            //————————————————————————————————————————————————————————————
           //设置标签内容
            let box_text= ` <img decoding="async" src="https://mp.weixin.qq.com/mp/qrcode?scene=10000004&amp;size=102&amp;__biz=MzU4OTc1NTI5Mw==&amp;mid=2247487235&amp;idx=1&amp;sn=afedbf6e40f5929e03c5c26fa3529639&amp;send_time=" width="82" height="82" alt="公众号:仰晨">
                            <div style="width:114px">    本脚本的作用在于学习的集合是初衷,边写边学是兴趣。</div>
                            <p>鄙人公众号:仰晨</p>`;//临时变量

            //创建一个默认隐藏的东东
            let move = createElement({type: 'div',
                                    attributes: {id: 'canSet'}}); //为了输出时标签不带双引号--直接写会带双引号会很神奇
            move.innerHTML = box_text;

            //插入父标签下
            document.getElementById("app").appendChild(move);

        }
    }else console.log("按钮已存在");
}//页面添加元素方法结束+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


//                              _   _
//    _______________          |*\_/*|________
//   |  ___________  |        ||_/-\_|______  |
//   | |           | |        | |           | |
//   | |   0   0   | |        | |   0   0   | |
//   | |     -     | |        | |     -     | |
//   | |   \___/   | |        | |   \___/   | |
//   | |___     ___| |        | |___________| |
//   |_____|\_/|_____|        |_______________|
//     _|__|/ \|_|_.............._|________|_
//    / ********** \            / ********** \
//  /  ************  \        /  ************  \
// --------------------      --------------------



//——————————————添加样式(分离操作)——————————————————————————————2023.1.25 begin
{
    let style=`
    #setText{
        position: fixed;
        right: 0px;
        bottom: 20px;
        width: 40px;
        z-index: 9999;
    }
    #see{
        position: absolute;
        top: 200px;
        left: 100%;
        width: 20px;

    }

    #see,
    #setText{
        border: 2px #fdbaba solid;
        background-color: #ffffff00;
        color: #FF6699;
        text-align: center;
        cursor: pointer;
        font-weight: 555;
        border-radius: 5px;
        transition: all .3s;
        opacity: 50%;
    }

    #setText:hover,
    #see:hover{
        background-color: #FFECF1;
        opacity: 100%;
    }


    #canSet{
         display: flex;
		 flex-wrap: wrap;
         position: fixed;
         right: -250px;
         transition: right .5s;
         bottom: 50px;
         width: 200px;
		 color: #9f8686;
         background-color: #e9b8fa59;
		 border-radius: 6px;
		 box-shadow: 3px 6px 10px 0px #8f9ca1;
		 border: 2px #fff solid;

    }

	#setText:hover+#canSet{
        right: 10px;
	}
    #canSet:hover{
		right: 15px;
	}

    /*----------2023.4.20---------------*/
    	/*进度样式*/
	[class="jindu"]{
        color: #d3d3d373;
		position: absolute;
		top: 16px;
		left: 1px;
		height: 20px;
		width: 400px;
	}
	.jindu::before {
  		content: " ";
	}

	/*为进度标签修改列表的样式*/
	.multi-page-v1.small-mode .cur-list .list-box li{
		overflow: visible;
		position: relative;
	}

	/*浮动在列表 进度的样式*/
	.multi-page-v1.small-mode .cur-list .list-box li :hover .jindu {
		/*color: #d3d3d3;2023.5.4换个颜色看看*/
        color: #f2bfbf;
	}

		/*浮动在列表 进度后追加的样式*/
	.multi-page-v1.small-mode .cur-list .list-box li :hover .jindu::before {
  		background-color: #fff;
		width: 400px;
		display: inline-block;
		position: absolute;
		z-index: -1;
	}

    /*给当前播放列添加一点样式2023.4.21*/
	[class="list-box"] [class="on"]::before,
	[class="list-box"] [class="watched on"]::before{
		background-color: #fff;
		width: 400px;
		left: 1px;
		top: 15px;
		position: absolute;
		content: " ";
		z-index: -1
	}
    `;

    //cursor:pointer;变小手   :hover碰到触发    transition: all .5s;过渡动画0.5秒   display: flex;弹性盒子


    let ele=document.createElement("style");
    ele.innerHTML=style;
    document.getElementsByTagName('head')[0].appendChild(ele);
}
//——————————————————————————————————————————————————————————