您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Maximize all video players.Support Piture-in-picture.
当前为
// ==UserScript== // @name Maximize Video(improve) // @name:zh-CN 视频网页全屏(改+) // @namespace https://github.com/ryomahan // @description Maximize all video players.Support Piture-in-picture. // @description:zh-CN 让所有视频网页全屏,开启画中画功能 // @author 冻猫, ryomahan, YeSilin // @include * // @exclude *www.w3school.com.cn* // @version 12.5.1 // @run-at document-end // @license MIT // ==/UserScript== (() => { const gv = { isFull: false, isIframe: false, autoCheckCount: 0, }; //Html5规则[播放器最外层],适用于无法自动识别的自适应大小HTML5播放器 const html5Rules = { "www.acfun.cn": [".player-container .player"], "www.bilibili.com": ["#bilibiliPlayer"], "www.douyu.com": ["#js-player-video-case"], "www.huya.com": ["#videoContainer"], "www.twitch.tv": [".player"], "www.youtube.com": ["#ytd-player"], "www.miguvideo.com": ["#mod-player"], "www.yy.com": ["#player"], "*weibo.com": ['[aria-label="Video Player"]', ".html5-video-live .html5-video"], "v.huya.com": ["#video_embed_flash>div"], }; //通用html5播放器 const generalPlayerRules = [".dplayer", ".video-js", ".jwplayer", "[data-player]"]; if (window.top !== window.self) { gv.isIframe = true; } if (navigator.language.toLocaleLowerCase() == "zh-cn") { gv.btnText = { max: "网页全屏", pip: "画中画", tip: "Iframe内视频,请用鼠标点击视频后重试", }; } else { gv.btnText = { max: "Maximize", pip: "PicInPic", tip: "Iframe video. Please click on the video and try again", }; } const tool = { print(log) { const now = new Date(); const year = now.getFullYear(); const month = (now.getMonth() + 1 < 10 ? "0" : "") + (now.getMonth() + 1); const day = (now.getDate() < 10 ? "0" : "") + now.getDate(); const hour = (now.getHours() < 10 ? "0" : "") + now.getHours(); const minute = (now.getMinutes() < 10 ? "0" : "") + now.getMinutes(); const second = (now.getSeconds() < 10 ? "0" : "") + now.getSeconds(); const timenow = "[" + year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second + "]"; console.log(timenow + "[Maximize Video] > " + log); }, getRect(element) { const rect = element.getBoundingClientRect(); const scroll = tool.getScroll(); return { pageX: rect.left + scroll.left, pageY: rect.top + scroll.top, screenX: rect.left, screenY: rect.top, }; }, isHalfFullClient(element) { const client = tool.getClient(); const rect = tool.getRect(element); if ( (Math.abs(client.width - element.offsetWidth) < 21 && rect.screenX < 20) || (Math.abs(client.height - element.offsetHeight) < 21 && rect.screenY < 10) ) { if ( Math.abs(element.offsetWidth / 2 + rect.screenX - client.width / 2) < 21 && Math.abs(element.offsetHeight / 2 + rect.screenY - client.height / 2) < 21 ) { return true; } else { return false; } } else { return false; } }, isAllFullClient(element) { const client = tool.getClient(); const rect = tool.getRect(element); if ( Math.abs(client.width - element.offsetWidth) < 21 && rect.screenX < 20 && Math.abs(client.height - element.offsetHeight) < 21 && rect.screenY < 10 ) { return true; } else { return false; } }, getScroll() { return { left: document.documentElement.scrollLeft || document.body.scrollLeft, top: document.documentElement.scrollTop || document.body.scrollTop, }; }, getClient() { return { width: document.compatMode == "CSS1Compat" ? document.documentElement.clientWidth : document.body.clientWidth, height: document.compatMode == "CSS1Compat" ? document.documentElement.clientHeight : document.body.clientHeight, }; }, addStyle(css) { const style = document.createElement("style"); style.type = "text/css"; const node = document.createTextNode(css); style.appendChild(node); document.head.appendChild(style); return style; }, matchRule(str, rule) { return new RegExp("^" + rule.split("*").join(".*") + "$").test(str); }, createButton(id) { const btn = document.createElement("tbdiv"); btn.id = id; btn.onclick = () => { maximize.playerControl(); }; document.body.appendChild(btn); return btn; }, async addTip(str) { if (!document.getElementById("catTip")) { const tip = document.createElement("tbdiv"); tip.id = "catTip"; tip.innerHTML = str; (tip.style.cssText = 'transition: all 0.8s ease-out;background: none repeat scroll 0 0 #27a9d8;color: #FFFFFF;font: 1.1em "微软雅黑";margin-left: -250px;overflow: hidden;padding: 10px;position: fixed;text-align: center;bottom: 100px;z-index: 300;'), document.body.appendChild(tip); tip.style.right = -tip.offsetWidth - 5 + "px"; await new Promise((resolve) => { tip.style.display = "block"; setTimeout(() => { tip.style.right = "25px"; resolve("OK"); }, 300); }); await new Promise((resolve) => { setTimeout(() => { tip.style.right = -tip.offsetWidth - 5 + "px"; resolve("OK"); }, 3500); }); await new Promise((resolve) => { setTimeout(() => { document.body.removeChild(tip); resolve("OK"); }, 1000); }); } }, }; const setButton = { init() { if (!document.getElementById("playerControlBtn")) { init(); } if (gv.isIframe && tool.isHalfFullClient(gv.player)) { window.parent.postMessage("iframeVideo", "*"); return; } this.show(); }, show() { gv.player.removeEventListener("mouseleave", handle.leavePlayer, false); gv.player.addEventListener("mouseleave", handle.leavePlayer, false); if (!gv.isFull) { document.removeEventListener("scroll", handle.scrollFix, false); document.addEventListener("scroll", handle.scrollFix, false); } gv.controlBtn.style.display = "block"; gv.controlBtn.style.visibility = "visible"; if (document.pictureInPictureEnabled && gv.player.nodeName != "OBJECT" && gv.player.nodeName != "EMBED") { gv.picinpicBtn.style.display = "block"; gv.picinpicBtn.style.visibility = "visible"; } this.locate(); }, locate() { let escapeHTMLPolicy; const hasTrustedTypes = Boolean(window.trustedTypes && window.trustedTypes.createPolicy); if (hasTrustedTypes) { escapeHTMLPolicy = window.trustedTypes.createPolicy("myEscapePolicy", { createHTML: (string, sink) => string, }); } const playerRect = tool.getRect(gv.player); gv.controlBtn.style.opacity = "0.5"; gv.controlBtn.innerHTML = hasTrustedTypes ? escapeHTMLPolicy.createHTML(gv.btnText.max) : gv.btnText.max; gv.controlBtn.style.top = playerRect.screenY - 20 + "px"; // 网页全屏按钮位置,Maximize button gv.controlBtn.style.left = playerRect.screenX - 64 + gv.player.offsetWidth + "px"; gv.picinpicBtn.style.opacity = "0.5"; gv.picinpicBtn.innerHTML = hasTrustedTypes ? escapeHTMLPolicy.createHTML(gv.btnText.pip) : gv.btnText.pip; gv.picinpicBtn.style.top = gv.controlBtn.style.top; // 画中画按钮位置,PicInPic button gv.picinpicBtn.style.left = playerRect.screenX - 64 + gv.player.offsetWidth - 54 + "px"; }, }; const handle = { getPlayer(e) { if (gv.isFull) { return; } gv.mouseoverEl = e.target; const hostname = document.location.hostname; let players = []; for (let i in html5Rules) { if (tool.matchRule(hostname, i)) { for (let html5Rule of html5Rules[i]) { if (document.querySelectorAll(html5Rule).length > 0) { for (let player of document.querySelectorAll(html5Rule)) { players.push(player); } } } break; } } if (players.length == 0) { for (let generalPlayerRule of generalPlayerRules) { if (document.querySelectorAll(generalPlayerRule).length > 0) { for (let player of document.querySelectorAll(generalPlayerRule)) { players.push(player); } } } } if (players.length == 0 && e.target.nodeName != "VIDEO" && document.querySelectorAll("video").length > 0) { const videos = document.querySelectorAll("video"); for (let v of videos) { const vRect = v.getBoundingClientRect(); if ( e.clientX >= vRect.x - 2 && e.clientX <= vRect.x + vRect.width + 2 && e.clientY >= vRect.y - 2 && e.clientY <= vRect.y + vRect.height + 2 && v.offsetWidth > 399 && v.offsetHeight > 220 ) { players = []; players[0] = handle.autoCheck(v); gv.autoCheckCount = 1; break; } } } if (players.length > 0) { const path = e.path || e.composedPath(); for (let v of players) { if (path.indexOf(v) > -1) { gv.player = v; setButton.init(); return; } } } switch (e.target.nodeName) { case "VIDEO": case "OBJECT": case "EMBED": if (e.target.offsetWidth > 399 && e.target.offsetHeight > 220) { gv.player = e.target; setButton.init(); } break; default: handle.leavePlayer(); } }, autoCheck(v) { let tempPlayer, el = v; gv.playerChilds = []; gv.playerChilds.push(v); while ((el = el.parentNode)) { if (Math.abs(v.offsetWidth - el.offsetWidth) < 15 && Math.abs(v.offsetHeight - el.offsetHeight) < 15) { tempPlayer = el; gv.playerChilds.push(el); } else { break; } } return tempPlayer; }, leavePlayer() { if (gv.controlBtn.style.visibility == "visible") { gv.controlBtn.style.opacity = ""; gv.controlBtn.style.visibility = ""; gv.picinpicBtn.style.opacity = ""; gv.picinpicBtn.style.visibility = ""; gv.player.removeEventListener("mouseleave", handle.leavePlayer, false); document.removeEventListener("scroll", handle.scrollFix, false); } }, scrollFix(e) { clearTimeout(gv.scrollFixTimer); gv.scrollFixTimer = setTimeout(() => { setButton.locate(); }, 20); }, hotKey(e) { //默认退出键为ESC。需要修改为其他快捷键的请搜索"keycode",修改为按键对应的数字。 if (e.keyCode == 27) { maximize.playerControl(); } //默认画中画快捷键为F2。 if (e.keyCode == 113) { handle.pictureInPicture(); } }, async receiveMessage(e) { switch (e.data) { case "iframePicInPic": tool.print("messege:iframePicInPic"); if (!document.pictureInPictureElement) { await document .querySelector("video") .requestPictureInPicture() .catch((error) => { tool.addTip(gv.btnText.tip); }); } else { await document.exitPictureInPicture(); } break; case "iframeVideo": tool.print("messege:iframeVideo"); if (!gv.isFull) { gv.player = gv.mouseoverEl; setButton.init(); } break; case "parentFull": tool.print("messege:parentFull"); gv.player = gv.mouseoverEl; if (gv.isIframe) { window.parent.postMessage("parentFull", "*"); } maximize.checkParent(); maximize.fullWin(); if (getComputedStyle(gv.player).left != "0px") { tool.addStyle( "#htmlToothbrush #bodyToothbrush .playerToothbrush {left:0px !important;width:100vw !important;}" ); } gv.isFull = true; break; case "parentSmall": tool.print("messege:parentSmall"); if (gv.isIframe) { window.parent.postMessage("parentSmall", "*"); } maximize.smallWin(); break; case "innerFull": tool.print("messege:innerFull"); if (gv.player.nodeName == "IFRAME") { gv.player.contentWindow.postMessage("innerFull", "*"); } maximize.checkParent(); maximize.fullWin(); break; case "innerSmall": tool.print("messege:innerSmall"); if (gv.player.nodeName == "IFRAME") { gv.player.contentWindow.postMessage("innerSmall", "*"); } maximize.smallWin(); break; } }, pictureInPicture() { if (!document.pictureInPictureElement) { if (gv.player) { if (gv.player.nodeName == "IFRAME") { gv.player.contentWindow.postMessage("iframePicInPic", "*"); } else { gv.player.parentNode.querySelector("video").requestPictureInPicture(); } } else { document.querySelector("video").requestPictureInPicture(); } } else { document.exitPictureInPicture(); } }, }; const maximize = { playerControl() { if (!gv.player) { return; } this.checkParent(); if (!gv.isFull) { if (gv.isIframe) { window.parent.postMessage("parentFull", "*"); } if (gv.player.nodeName == "IFRAME") { gv.player.contentWindow.postMessage("innerFull", "*"); } this.fullWin(); if (gv.autoCheckCount > 0 && !tool.isHalfFullClient(gv.playerChilds[0])) { if (gv.autoCheckCount > 10) { for (let v of gv.playerChilds) { v.classList.add("videoToothbrush"); } return; } const tempPlayer = handle.autoCheck(gv.playerChilds[0]); gv.autoCheckCount++; maximize.playerControl(); gv.player = tempPlayer; maximize.playerControl(); } else { gv.autoCheckCount = 0; } } else { if (gv.isIframe) { window.parent.postMessage("parentSmall", "*"); } if (gv.player.nodeName == "IFRAME") { gv.player.contentWindow.postMessage("innerSmall", "*"); } this.smallWin(); } }, checkParent() { if (gv.isFull) { return; } gv.playerParents = []; let full = gv.player; while ((full = full.parentNode)) { if (full.nodeName == "BODY") { break; } if (full.getAttribute) { gv.playerParents.push(full); } } }, fullWin() { if (!gv.isFull) { document.removeEventListener("mouseover", handle.getPlayer, false); gv.backHtmlId = document.body.parentNode.id; gv.backBodyId = document.body.id; gv.leftBtn.style.display = "block"; gv.rightBtn.style.display = "block"; gv.picinpicBtn.style.display = ""; gv.controlBtn.style.display = ""; this.addClass(); const hostname = document.location.hostname; // 为 Youtube 做特殊处理 if ( hostname.includes("www.youtube.com") && !document.querySelector("#player-theater-container #movie_player") && document.querySelector(".html5-video-container").clientWidth - document.querySelector(".ytp-chrome-bottom").clientWidth > 24 ) { document.querySelector("#movie_player .ytp-size-button").click(); gv.ytbStageChange = true; } // 为 B 站做特殊处理 if (hostname.includes("bilibili")) { document.querySelector(".right-container")?.style.removeProperty("display"); document.querySelector("#biliMainHeader")?.style.removeProperty("display"); } } gv.isFull = true; }, addClass() { document.body.parentNode.id = "htmlToothbrush"; document.body.id = "bodyToothbrush"; for (let v of gv.playerParents) { v.classList.add("parentToothbrush"); //父元素position:fixed会造成层级错乱 if (getComputedStyle(v).position == "fixed") { v.classList.add("absoluteToothbrush"); } } gv.player.classList.add("playerToothbrush"); if (gv.player.nodeName == "VIDEO") { gv.backControls = gv.player.controls; gv.player.controls = true; } window.dispatchEvent(new Event("resize")); }, smallWin() { document.body.parentNode.id = gv.backHtmlId; document.body.id = gv.backBodyId; for (let v of gv.playerParents) { v.classList.remove("parentToothbrush"); v.classList.remove("absoluteToothbrush"); } gv.player.classList.remove("playerToothbrush"); if ( document.location.hostname == "www.youtube.com" && gv.ytbStageChange && document.querySelector("#player-theater-container #movie_player") ) { document.querySelector("#movie_player .ytp-size-button").click(); gv.ytbStageChange = false; } if (gv.player.nodeName == "VIDEO") { gv.player.controls = gv.backControls; } gv.leftBtn.style.display = ""; gv.rightBtn.style.display = ""; gv.controlBtn.style.display = ""; document.addEventListener("mouseover", handle.getPlayer, false); window.dispatchEvent(new Event("resize")); const hostname = document.location.hostname; if (hostname.includes("bilibili")) { document.querySelector(".right-container")?.style.setProperty("display", "none"); document.querySelector("#biliMainHeader")?.style.setProperty("display", "none"); } gv.isFull = false; }, }; const init = () => { gv.picinpicBtn = document.createElement("tbdiv"); gv.picinpicBtn.id = "picinpicBtn"; gv.picinpicBtn.onclick = () => { handle.pictureInPicture(); }; document.body.appendChild(gv.picinpicBtn); gv.controlBtn = tool.createButton("playerControlBtn"); gv.leftBtn = tool.createButton("leftFullStackButton"); gv.rightBtn = tool.createButton("rightFullStackButton"); if (getComputedStyle(gv.controlBtn).position != "fixed") { tool.addStyle( [ "#htmlToothbrush #bodyToothbrush .parentToothbrush .bilibili-player-video {margin:0 !important;}", "#htmlToothbrush, #bodyToothbrush {overflow:hidden !important;zoom:100% !important;}", "#htmlToothbrush #bodyToothbrush .parentToothbrush {overflow:visible !important;z-index:auto !important;transform:none !important;-webkit-transform-style:flat !important;transition:none !important;contain:none !important;}", "#htmlToothbrush #bodyToothbrush .absoluteToothbrush {position:absolute !important;}", "#htmlToothbrush #bodyToothbrush .playerToothbrush {position:fixed !important;top:0px !important;left:0px !important;width:100vw !important;height:100vh !important;max-width:none !important;max-height:none !important;min-width:0 !important;min-height:0 !important;margin:0 !important;padding:0 !important;z-index:2147483646 !important;border:none !important;background-color:#000 !important;transform:none !important;}", "#htmlToothbrush #bodyToothbrush .parentToothbrush video {object-fit:contain !important;}", "#htmlToothbrush #bodyToothbrush .parentToothbrush .videoToothbrush {width:100vw !important;height:100vh !important;}", '#playerControlBtn {text-shadow: none;visibility:hidden;opacity:0;display:none;transition: all 0.5s ease;cursor: pointer;font: 12px "微软雅黑";margin:0;width:64px;height:20px;line-height:20px;border:none;text-align: center;position: fixed;z-index:2147483647;background-color: #27A9D8;color: #FFF;} #playerControlBtn:hover {visibility:visible;opacity:1;background-color:#2774D8;}', '#picinpicBtn {text-shadow: none;visibility:hidden;opacity:0;display:none;transition: all 0.5s ease;cursor: pointer;font: 12px "微软雅黑";margin:0;width:53px;height:20px;line-height:20px;border:none;text-align: center;position: fixed;z-index:2147483647;background-color: #27A9D8;color: #FFF;} #picinpicBtn:hover {visibility:visible;opacity:1;background-color:#2774D8;}', "#leftFullStackButton{display:none;position:fixed;width:1px;height:100vh;top:0;left:0;z-index:2147483647;background:#000;}", "#rightFullStackButton{display:none;position:fixed;width:1px;height:100vh;top:0;right:0;z-index:2147483647;background:#000;}", ].join("\n") ); } document.addEventListener("mouseover", handle.getPlayer, false); document.addEventListener("keydown", handle.hotKey, false); window.addEventListener("message", handle.receiveMessage, false); tool.print("Ready"); }; init(); })();