您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在哔哩哔哩实现类似viewsync的功能。WIP。装好以后功能入口位于t.bilibili.com右侧栏。
// ==UserScript== // @name Bilibili ViewSync // @namespace http://tampermonkey.net/ // @version 0.2 // @description 在哔哩哔哩实现类似viewsync的功能。WIP。装好以后功能入口位于t.bilibili.com右侧栏。 // @author yuyuyzl // @match https://live.bilibili.com/* // @match https://t.bilibili.com/* // @grant unsafeWindow // @grant GM_getValue // @grant GM_setValue // @grant GM_setClipboard // @grant GM_info // ==/UserScript== var config={ "roomids":[], }; (function() { 'use strict'; var reloadConfig=function(){ Object.keys(config).forEach(function(key){ //console.log(key,config[key]); var valuet=GM_getValue(key); if(valuet!=null){ config[key]=valuet; }else { GM_setValue(key,config[key]); } }); }; reloadConfig(); // throttle 和 debouce 函数的底层实现 var limit = function(func, wait, debounce) { var timeout; return function() { var context = this, args = arguments; // 封装函数,用于延迟调用 var throttler = function() { // 只是节流函数的时候,对其timeout进行赋值为null,这样可以设置下一次的setTimtout timeout = null; func.apply(context, args); }; // 如果debouce是true的话,前一个函数的调用timeout会被清空,不会被执行 // 就是debounce函数的调用,这个前一个函数的不会执行.下面会重新设定setTimeout用于 // 执行这一次的调用. // 但是如果是throttle函数,则会执行前一个函数的调用,同时下面的setTimeout在 // 函数没有运行的时候,是无法再次设定的. if (debounce) clearTimeout(timeout); // 如果debouce是true 或者 timeout 为空的情况下,设置setTimeout if (debounce || !timeout) timeout = setTimeout(throttler, wait); }; }; // throttle 节流函数 var throttle = function(func, wait) { return limit(func, wait, false); }; // debouce 多次调用,只执行最后一次. var debounce = function(func, wait) { return limit(func, wait, true); }; if(window.top!==window){ setInterval(()=>{document.querySelector("body").className=" player-full-win over-hidden hide-aside-area";},100); } if(window.location.href.match(/.*t.bilibili.com.*/)){ window.onload=function() { var mystyle=document.createElement("style"); mystyle.innerHTML= "<!-- --> .ratio{\n display: flex;\n flex-grow: 1;\n }\n #root{\n width: 100vw;height: 100vh;margin: 0;\n display: flex;\n }\n iframe{\n position: absolute;\n border: 0;\n background: #FFF;\n top:0;\n left: 0;\n }\n .mypanel{\n position: relative;\n width: 100%;\n background-color: #fff;\n border-radius: 4px;\n margin: 8px 0;\n }\n .mypanel .title{\n padding-top: 12px;\n padding-left: 16px;\n padding-bottom: 8px;\n }\n .mypanel div{\nmargin-top:4px;\n}\n.mypanel button{\n-webkit-appearance: none;\nwidth: 24px;\nfont-size: 12px;\ncolor: #00a1d6;\nborder: 1px solid #00a1d6;\nborder-radius: 4px;\nbackground: transparent;\ncursor: pointer;\n}\n .mypanel .more-button{\n position: absolute;\n width: 30px;\n height: 20px;\n top: 13px;\n right: 20px;\n }"; document.getElementsByTagName("head")[0].appendChild(mystyle); var mypanel=document.createElement("div"); mypanel.className="mypanel"; mypanel.innerHTML="<p class=\"title tc-black fs-14 ls-0\">Bili ViewSync</p>\n<a href=\'https://live.bilibili.com/sync\' style=\'color: darkgray\' target=\'_blank\' class=\'more-button\'>Go></a>\n<div style=\'padding-left: 16px;padding-bottom: 14px;\'>\n <input type=\'text\' id=\'bvs-addinput\' >\n <button id=\'bvs-add\'>+</button>\n <div id=\'rooms-container\'></div>\n</div>\n"; document.querySelector(".live-panel").after(mypanel); function addroomid(id,doAdd){ if(doAdd && config.roomids.indexOf(id)>=0)return; if(id==null)return; if(doAdd){ config.roomids.push(id); GM_setValue("roomids",config["roomids"]); } let line=document.createElement("div"); let buttonDel=document.createElement("button"); buttonDel.innerText="-"; buttonDel.onclick=function () { document.getElementById("rooms-container").removeChild(line); config.roomids.splice(config.roomids.indexOf(id),1); GM_setValue("roomids",config["roomids"]); } line.appendChild(buttonDel); line.appendChild(document.createTextNode(id)); document.getElementById("rooms-container").appendChild(line); } document.getElementById("bvs-add").onclick=function () { addroomid(document.getElementById("bvs-addinput").value.match(/[0-9]+/)[0],true); document.getElementById("bvs-addinput").value=""; }; for(let id of config.roomids)addroomid(id,false); } } if(window.location.href.match(/.*live.bilibili.com\/sync.*/)){ var body; var clientRatio=[]; var splitNow=[]; var roomids=config.roomids; if(roomids.length==0){ alert("直播间列表为空,请先去动态首页添加!"); window.location.href="https://t.bilibili.com/"; } var possibleSplit=solve(roomids.length); var iframes=roomids.map(id=>{ let iframe=document.createElement("iframe"); iframe.setAttribute("src","https://live.bilibili.com/"+id); return iframe; }); var iframeCount=0; function solve( x,limit) { if(limit===undefined)limit=x-1; if (x === 1) return [[1]]; let ret = []; for (let i = 1; i < Math.min(limit, x-1) + 1; i++) { let sub = solve(i, i - 1); let now = solve(x-i, i); for (let info of sub) for (let more of now) if (JSON.stringify(info) === "[1]") { //console.log("1*" + " " + JSON.stringify(info) + " " + JSON.stringify(more) + " " + JSON.stringify(info.concat(more))); ret.push(more.concat(info)); } else { //console.log("2*" + " " + JSON.stringify(info) + " " + JSON.stringify(more) + " " + JSON.stringify([info].concat(more))); ret.push(more.concat([info])); } } if(limit>=x){ let now=[]; for (let more of ret){ if(JSON.stringify(more) !== "[1]")now.push([more]); } ret=ret.concat(now); } return ret } function refreshFramesPos(){ clientRatio=[body.clientWidth,body.clientHeight]; let best=null; let bestArea=0; for(let i of possibleSplit){ var ratio=getParentRatio(i,false); var area=Math.min(ratio[0]*ratio[1]*(clientRatio[0]/ratio[0])*(clientRatio[0]/ratio[0]),ratio[0]*ratio[1]*(clientRatio[1]/ratio[1])*(clientRatio[1]/ratio[1])); if(area>bestArea){ best=[i,false]; bestArea=area; } var ratio=getParentRatio(i,true); var area=Math.min(ratio[0]*ratio[1]*(clientRatio[0]/ratio[0])*(clientRatio[0]/ratio[0]),ratio[0]*ratio[1]*(clientRatio[1]/ratio[1])*(clientRatio[1]/ratio[1])); if(area>bestArea){ best=[i,true]; bestArea=area; } } //console.log(JSON.stringify(best)); iframeCount=0; if(JSON.stringify(best)!==JSON.stringify(splitNow)) { splitNow=best; let newChild = getDOMNodes(best[0], best[1]); newChild.id = "splitter"; console.log(newChild); console.log(newChild.myRatio); body.replaceChild(newChild, body.children.splitter); } for(let i=0;i<iframes.length;i++){ let parent=document.getElementById("frame"+i); iframes[i].style.top=parent.offsetTop+"px"; iframes[i].style.left=parent.offsetLeft+"px"; iframes[i].style.width=parent.offsetWidth+"px"; iframes[i].style.height=parent.offsetHeight+"px"; } } var refreshFramesPosDebounced=debounce(refreshFramesPos,1000); window.onresize=function(){ //console.log(body.clientWidth+" "+body.clientHeight); refreshFramesPosDebounced(); }; window.onload=function(){ document.getElementsByTagName("head")[0].innerHTML="<style>\n" + " .ratio{\n" + " display: flex;\n" + " flex-grow: 1;\n" + " }\n" + " #root{\n" + " width: 100vw;height: 100vh;margin: 0;\n" + " display: flex;\n" + " }\n" + " iframe{\n" + " position: absolute;\n" + " border: 0;\n" + " background: #FFF;\n" + " top:0;\n" + " left: 0;\n" + " }\n .mypanel{\n position: relative;\n width: 268px;\n background-color: #fff;\n border-radius: 4px;\n margin-bottom: 8px;\n }\n .mypanel .title{\n padding-top: 12px;\n padding-left: 16px;\n padding-bottom: 8px;\n }\n" + "</style>"; document.getElementsByTagName("body")[0].outerHTML="<body style=\"width: 100vw;height: 100vh;margin: 0\">\n" + "<div id=\"root\"><div id=\"splitter\"/></div>\n" + "<div id=\"frames\"></div>\n" + "</body>"; body=document.getElementById("root"); for(let iframe of iframes)document.getElementById("frames").appendChild(iframe); window.onresize(); }; var videoW=16; var videoH=9; function getParentRatio(arr,isVertical){ let ratio=null; if(Array.isArray(arr)){ for(let item of arr){ let res=getParentRatio(item,!isVertical); if(ratio==null)ratio=res;else if (isVertical) ratio[1]+=res[1]/res[0]*ratio[0];else ratio[0]+=res[0]/res[1]*ratio[1]; } }else return [videoW,videoH]; return ratio; } function getDOMNodes(arr,isVertical){ let ratio=null; if(Array.isArray(arr)){ let dom=document.createElement("div"); dom.className="ratio container"; if (isVertical) dom.style.flexDirection="column"; for(let item of arr){ let newNode=getDOMNodes(item,!isVertical); if(ratio==null){ ratio=newNode.myRatio; if (isVertical) { newNode.style.flexGrow=newNode.myRatio[1]/newNode.myRatio[0]*ratio[0]; }else { newNode.style.flexGrow=newNode.myRatio[0]/newNode.myRatio[1]*ratio[1]; } }else if (isVertical) { ratio[1]+=newNode.myRatio[1]/newNode.myRatio[0]*ratio[0]; newNode.style.flexGrow=newNode.myRatio[1]/newNode.myRatio[0]*ratio[0]; }else { ratio[0]+=newNode.myRatio[0]/newNode.myRatio[1]*ratio[1]; newNode.style.flexGrow=newNode.myRatio[0]/newNode.myRatio[1]*ratio[1]; } dom.appendChild(newNode); } dom.myRatio=ratio; return dom; }else { let dom= document.createElement("div"); //dom.innerText="FRAME"; //dom.appendChild(iframes[iframeCount]); dom.id="frame"+iframeCount; iframeCount++; dom.className="ratio iframe"; dom.myRatio=[videoW,videoH]; return dom; } } } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址