Greasy Fork is available in English.
无需安装MacType,优化浏览器字体渲染效果,让每个页面的字体变得更有质感。默认使用“微软雅黑”字体,也可根据喜好自定义其他字体使用。脚本针对浏览器字体渲染提供了字体重写、字体平滑、字体缩放、字体描边、字体阴影、对特殊样式元素的过滤和许可、自定义等宽字体等高级功能。脚本支持全局渲染与个性化渲染功能,可通过“单击脚本管理器图标”或“使用快捷键”呼出配置界面进行参数配置。脚本已兼容绝大部分主流浏览器及主流脚本管理器,且兼容常用的油猴脚本和浏览器扩展。
这是个两年没更新的代码,你遇到的问题不是失效,而是产生脚本冲突,电脑配置差的会造成浏览器卡死。我无法理解为什么要用第三方的视频全屏和画中画代码,绝大部分视频网站都已经有这些功能了不是么?下面我只针对冲突部分修正了它的代码,你覆盖即可。
// ==UserScript==
// @name Maximize Video
// @name:zh-CN 视频网页全屏
// @namespace http://www.icycat.com
// @description Maximize all video players.Support Piture-in-picture.
// @description:zh-CN 让所有视频网页全屏,开启画中画功能
// @author 冻猫
// @include *
// @exclude *www.w3school.com.cn*
// @version 12.1
// @run-at document-end
// ==/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": ["#movie_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() {
const playerRect = tool.getRect(gv.player)
gv.controlBtn.style.opacity = "0.5"
gv.controlBtn.innerHTML = 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 = 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.className
gv.backBodyId = document.body.className
console.log({html:gv.backHtmlId,body:gv.backBodyId})
if (document.location.hostname == "www.youtube.com" && !document.querySelector("#player-theater-container #movie_player")) {
document.querySelector("#movie_player .ytp-size-button").click()
gv.ytbStageChange = true
}
gv.leftBtn.style.display = "block"
gv.rightBtn.style.display = "block"
gv.picinpicBtn.style.display = ""
gv.controlBtn.style.display = ""
this.addClass()
}
gv.isFull = true
},
addClass() {
document.body.parentNode.classList.add("htmlToothbrush")
document.body.classList.add("bodyToothbrush")
console.log({html:document.body.parentNode.className,body:document.body.className})
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.className = gv.backHtmlId
document.body.className = 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"))
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()
})()
这是个两年没更新的代码,你遇到的问题不是失效,而是产生脚本冲突,电脑配置差的会造成浏览器卡死。我无法理解为什么要用第三方的视频全屏和画中画代码,绝大部分视频网站都已经有这些功能了不是么?下面我只针对冲突部分修正了它的代码,你覆盖即可。
为什么要用百分浏览器的自带视频弹出和视频网页全屏插件呢,因为比谷歌自带的画中画强。
使用百分浏览器的自带视频弹出可以看B站的弹幕,而画中画是不行的,而且可以记住弹出后的位置和调整后的大小
使用视频网页全屏插件是因为百分自动自带看油管上的视频有问题显示全部画面,才用此插件弥补。
可能你不是我这种弹出视频的重度用户所以不理解,如果是就会抛弃谷歌自带另寻插件,因为画中画真不好用。
这里有个地方好像没改完? if (getComputedStyle(gv.player).left != "0px") { tool.addStyle("#htmlToothbrush #bodyToothbrush .playerToothbrush {left:0px !important;width:100vw !important;}") } 改成 if (getComputedStyle(gv.player).left != "0px") { tool.addStyle(".htmlToothbrush .bodyToothbrush .playerToothbrush {left:0px !important;width:100vw !important;}") } 就好啦。
这里有个地方好像没改完?
if (getComputedStyle(gv.player).left != "0px") {
tool.addStyle("#htmlToothbrush #bodyToothbrush .playerToothbrush {left:0px !important;width:100vw !important;}")
}
改成
if (getComputedStyle(gv.player).left != "0px") {
tool.addStyle(".htmlToothbrush .bodyToothbrush .playerToothbrush {left:0px !important;width:100vw !important;}")
}
就好啦。
感谢给出网页全屏插件的代码修改。
不过只针对视频网页全屏插件修改,而百分浏览器是失效的。
百分自带和网页全屏插件我都是必要的。因为字体更新导致失效,才提出问题,而字体渲染2023.10.03.1的版本目前够用了又没有大问题,所以还是停留在此版本了不更新了。
不过只针对视频网页全屏插件修改,而百分浏览器是失效的。
我很奇怪,为什么遇到问题总是要把责任推到别人头上呢,你自己检查过你本地的问题吗?
同样是CB,关闭了DW,最新版脚本,一切正常!看图:
不过只针对视频网页全屏插件修改,而百分浏览器是失效的。
我很奇怪,为什么遇到问题总是要把责任推到别人头上呢,你自己检查过你本地的问题吗?
同样是CB,关闭了DW,最新版脚本,一切正常!看图:
你也是很搞笑,凭啥说我遇到问题总是要把责任推到别人头上,我用百分浏览器安全模式也试过,只装篡改猴和最新字体插件才出问题,停用插件立马就正常了。我就是发现问题才反馈,我也没有怪到别人头上,有问题当然是反馈出来解决。
没错最新字体插件在我的电脑上百分自带和全屏插件都没问题,而我用B站回复,是因为作者不理解我为什么要使用百分浏览自带弹出和视频插件,我用B站来举例是因为我的需求,B站没问题不代表其他网站没问题。你在微博上的视频试试。
服嗎?弟弟。
CB上的視頻最大化和畫中畫方法也是4870腳本實現的,調用的是https://greasyfork.org/en/scripts/4870-video-full-screen-in-tab的低版本號v6.7的脚本,你提供的地址已經是v12.0了,雖然BUG也一大堆。
這種實現方式幾乎沒有什麽高明的地方,妳可以將CB瀏覽器的"显示视频独立窗口提示"關閉,只使用作者給你修正后的脚本就完事了。
還有一點要注意的是,你要用這個最大化視頻的脚本,在使用渲染脚本時別打開字體比例縮放,這些畫中畫脚本都沒有對縮放后的坐標修正過,肯定出問題。再問一遍,服嗎,弟弟?😁
赞 👍,肯花时间处理问题的用户着实不多。
使用视频的弹出重度用户,更新到 2023.11.04.1导致自带视频弹出和视频网页全屏插件(https://greasyfork.org/zh-CN/scripts/4870-maximize-video)失效无法最大化。关闭插件或退回上个版本2023.10.03.1就正常了。
使用的是百分浏览器5.0.1002.354 (Chromium 102.0.5005.167),篡改猴4.19.0