// ==UserScript== // @name Maximize Video // @name:zh-CN 视频网页全屏 // @namespace http://www.icycat.com // @description Maximize all video players // @description:zh-CN 让所有视频网页全屏 // @author 冻猫 // @include * // @exclude *www.w3school.com.cn* // @version 10.0 // @grant unsafeWindow // @run-at document-end // @downloadURL none // ==/UserScript== (function() { 'use strict'; var fullStatus = false, isIframe = false, isFullIframePlayer = false, isRbtn = true, parentArray = new Array(), backStyle = new Object(), mouse = { leave: 'listener', over: 'listener' }, browser, btnText, picinpicText, player, controlBtn, picinpicBtn, leftBtn, rightBtn; //Html5规则[overlay(鼠标在播放器上时的节点)|从overlay到player节点数(更精确)或player节点],适用于自适应大小HTML5播放器 var html5Rules = { 'tv.sohu.com': ['#player video|#player', '#player .x-gradient-top|#player'], '*gimy.tv': ['.plyr__poster|2', '.dplayer video|2'], 'cc.163.com': ['#comment-canvas|2', '#live-wrapper>video|2', '.live_container iframe|0'], 'ani.gamer.com.tw': ['#ani_video_html5_api|1'], 'www.thisav.com': ['#my-video_Shaka_api|1'], 'spankbang.com': ['#video_player_html5_api|1'], '*.autohome.com.cn': ['.ahvp-wrap .ahvp__video__shadow|2'], 'www.washingtonpost.com': ['.ctrls-overlay-center|4'], 'edition.cnn.com': ['.theoplayer-container div[style="position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; width: 100%; height: 100%;"]|3'], 'vidnode.net': ['#myVideo video|#myVideo'], 'k-vid.net': ['#myVideo video|#myVideo'], 'weibo.com': ['video|2'], 'pan.baidu.com': ['#video-root|#video-player'], 'www.nicovideo.jp': ['#UadPlayer|2'], 'thevideo.me': ['#vplayer video|1'], 'kimcartoon.me': ['#divContentVideo video|1'], 'www.dailymotion.com': ['.dmp_Player video|4', '.dmp_Player .np_button|6', '.dmp_Player .np_icon|7'], '*.youku.com': ['.yk-trigger-layer|3', '.youku-layer-logo|3', '.spv-logo|4', '.spv_shadow|2', '.live_shadow|2'], 'www.iqiyi.com': ['#flashbox video|2'], 'www.youtube.com': ['.html5-video-player video|2', '.ytp-player-content|1'], 'www.twitch.tv': ['.video-player__container iframe|8', '.pl-controls-top|6'], 'www.huya.com': ['#videoContainer .player-video|#videoContainer'], 'www.huomao.com': ['#my-gift-stage|#h5-playing-box'], 'www.icourse163.org': ['.ux-video-player .bbg|3'], 'www.panda.tv': ['#room-player-video-danmu div|.h5player-player-container', '.room-timeline-record-btn|.h5player-player-container'], 'vk.com': ['.videoplayer_media|1'], 'www.douyu.com': ['div[class^="video-container"]|#js-player-video-case'], 'store.steampowered.com': ['#highlight_player_area video|2'], 'vimeo.com': ['.player .target|1', '.player .cards|2'], 'ecchi.iwara.tv': ['#video-player video|1'], 'www.bilibili.com': ['#bilibiliPlayer .bilibili-player-video-subtitle|4', '#bilibiliPlayer video|4', '.bilibili-player-info|2'], 'live.bilibili.com': ['.bilibili-live-player-video-danmaku|2', '.bilibili-live-player-video-gift|2'], 'egame.qq.com': ['div[style^="overflow: hidden; white-space: nowrap; transform: translateZ(0px); position: relative;"]|div[id^="video-container"]'], '*.qq.com': ['.txp_player .txp_shadow|2'] }; //通用html5播放器 var generalHtml5Rules = ['.dplayer video|2', '.dplayer .dplayer-danmaku|2', '.video-js video|1']; //iframe播放器显示按钮规则 //iframe关键字id、classname、src var iframeRules = /youtube\.com\/embed|videoembed|player|movie|anime|flv|mp4|v\.youku\.com|www\.iqiyi\.com|v\.qq\.com|www\.le\.com/i; //网站域名 var iframeUrlRules = [ 'www.zxzjs.com', '8maple.ru', 'www.74xw.com', 'api.tianxianle.com', 'www.7nmg.com', 'www.kirikiri.tv', 'www.freebbbb.com', 'www.huffingtonpost.com', 'www.hanju.cc', 'www.freemvtv.com', 'twmeiju.com', '*fmovies*', 'www2.watchasian.co', 'putlocker.ninja', 'kisshentai.net', 'www.watchseries.ac', 'www.panda.tv', 'animeflv.net', 'www.vodlocker.city', 'projectwatchseries.com', 'reyanime.com' ]; //自动缩放内层内播放器规则 var fullIframePlayerRules = [ 'video.8maple.ru', 'api.tianxianle.com', 'vidnode.net', 'k-vid.net', 'v.qq.com', 'newplayer.jfrft.com', 'player.005.tv', 'player.xcmh.cc', 'www.auroravid.to', 'www.mp4upload.com', 'vodlocker.com', '52dongm.duapp.com' ]; //flash游戏页面,不在flash上显示还原按钮 var excludeRbtnRules = [ 'www.dmm.com', 'www.dmm.co.jp', 'www.4399.com', 'www.3366.com', 'flash.17173.com', 'www.7k7k.com' ]; if (excludeRbtnRules.indexOf(document.location.hostname) != -1) { isRbtn = false; } if (window.top !== window.self) { isIframe = true; } if (navigator.language.toLocaleLowerCase() == 'zh-cn') { btnText = { out: '网页全屏', inner: '内层全屏', restore: '还原大小' }; picinpicText = '画中画'; } else { btnText = { out: 'Maximize', inner: 'M
A
X', restore: 'Restore' }; picinpicText = 'PicInPic'; } if (/Firefox/i.test(navigator.userAgent)) { browser = 'firefox'; } else if (/Chrome/i.test(navigator.userAgent)) { browser = 'chrome'; } else { browser = 'other'; } var createButton = function(id) { var btn = document.createElement('tbdiv'); btn.id = id; btn.onclick = function() { maximize.playerControl(); }; document.body.appendChild(btn); return btn; }; var tool = { getRect: function(element) { var rect = element.getBoundingClientRect(); var scroll = tool.getScroll(); return { pageX: rect.left + scroll.left, pageY: rect.top + scroll.top, screenX: rect.left, screenY: rect.top }; }, isFullClient: function(element) { var client = tool.getClient(); var rect = tool.getRect(element); if (Math.abs(client.width - element.offsetWidth) < 21 && Math.abs(client.height - element.offsetHeight) < 21 && rect.screenY < 10 && rect.screenX < 20) { return true; } else { return false; } }, isHtml5FullClient: function(element) { var client = tool.getClient(); var rect = tool.getRect(element); var w = client.width - element.offsetWidth; var h = client.height - element.offsetHeight; if (w >= 0 && h >= 0) { if ((w < 21 && rect.screenX < 20) || (h < 21 && rect.screenY < 10)) { return true; } else { return false; } } else { return false; } }, getScroll: function() { return { left: document.documentElement.scrollLeft || document.body.scrollLeft, top: document.documentElement.scrollTop || document.body.scrollTop }; }, getClient: function() { return { width: document.compatMode == 'CSS1Compat' ? document.documentElement.clientWidth : document.body.clientWidth, height: document.compatMode == 'CSS1Compat' ? document.documentElement.clientHeight : document.body.clientHeight }; }, addStyle: function(css) { var style = document.createElement('style'); style.type = 'text/css'; var node = document.createTextNode(css); style.appendChild(node); document.head.appendChild(style); return style; }, matchRule: function(str, rule) { return new RegExp("^" + rule.split("*").join(".*") + "$").test(str); } }; var setButton = { init: function() { //防止页面脚本干扰,重新初始化样式 if (!document.getElementById('playerControlBtn')) { init(); } if (isIframe && !isFullIframePlayer && fullIframePlayerRules.indexOf(document.location.hostname) != -1) { if (player) { maximize.checkParent(); maximize.addClass(); tool.addStyle('#htmlToothbrush #bodyToothbrush .playerToothbrush {left:0px !important;width:100vw !important;}'); isFullIframePlayer = true; } } if (tool.isFullClient(player) || isFullIframePlayer) { return; } if (isIframe && player.nodeName == 'VIDEO' && tool.isHtml5FullClient(player)) { return; } this.show(); }, show: function() { try { player.addEventListener('mouseleave', handle.leavePlayer, false); } catch (e) { mouse.leave = player.onmouseleave; player.onmouseleave = function() { handle.leavePlayer(); player.onmouseleave = mouse.leave; }; } if (!fullStatus) { document.addEventListener('scroll', handle.scrollFix, false); } controlBtn.style.display = 'block'; controlBtn.style.visibility = 'visible'; this.locate(); }, locate: function() { var playerRect = tool.getRect(player); if (playerRect.pageY < 20 || fullStatus) { if (fullStatus) { controlBtn.classList.remove('playerControlBtnCol'); playerRect.screenY = playerRect.screenY + 50; playerRect.screenX = playerRect.screenX - 30; controlBtn.innerHTML = btnText.restore; } else { playerRect.screenY = playerRect.screenY + 20; if (Math.abs(tool.getClient().width - player.offsetWidth) < 21 && Math.abs(tool.getClient().height - player.offsetHeight) > 21) { playerRect.screenX = playerRect.screenX + 44; } else { playerRect.screenX = playerRect.screenX + 64; } controlBtn.classList.add('playerControlBtnCol'); if (isIframe) { controlBtn.innerHTML = btnText.inner; } else { controlBtn.innerHTML = btnText.out; } } if (browser == 'firefox' && fullStatus) { controlBtn.style.opacity = '1'; } else { controlBtn.style.opacity = '0.5'; } } else { controlBtn.classList.remove('playerControlBtnCol'); controlBtn.style.opacity = '0.5'; controlBtn.innerHTML = btnText.out; } controlBtn.style.top = playerRect.screenY - 20 + 'px'; controlBtn.style.left = playerRect.screenX - 64 + player.offsetWidth + 'px'; if (document.pictureInPictureEnabled) { picinpicBtn.innerHTML = picinpicText; picinpicBtn.style.display = 'block'; picinpicBtn.style.visibility = 'visible'; picinpicBtn.style.opacity = '0.5'; picinpicBtn.style.top = controlBtn.style.top; picinpicBtn.style.left = playerRect.screenX - 64 + player.offsetWidth - 54 + 'px'; } } }; var handle = { getPlayer: function(e) { if (fullStatus) { return; } var target = e.target; var hostname = document.location.hostname; var overlayRules; for (var i in html5Rules) { if (tool.matchRule(hostname, i)) { overlayRules = html5Rules[i]; break; } } if (!overlayRules) { overlayRules = generalHtml5Rules; } if (overlayRules) { var overlay = [], playerNum = []; for (var i = 0; i < overlayRules.length; i++) { var rules = overlayRules[i].split('|'); overlay[i] = document.querySelectorAll(rules[0]); playerNum[i] = rules[1]; } for (var i = 0; i < overlay.length; i++) { for (var j = 0; j < overlay[i].length; j++) { if (overlay[i][j] == target) { var html5Player = target; if (!isNaN(Number(playerNum[i]))) { for (var k = 0; k < playerNum[i]; k++) { html5Player = html5Player.parentNode; } } else { html5Player = document.querySelector(playerNum[i]); } player = html5Player; setButton.init(); return; } } } } switch (target.nodeName) { case 'IFRAME': var isVideoIframe = false; for (var i = 0; i < iframeUrlRules.length; i++) { if (tool.matchRule(hostname, iframeUrlRules[i])) { isVideoIframe = true; break; } } if (!iframeRules.test(target.className) && !iframeRules.test(target.src) && !iframeRules.test(target.id) && !isVideoIframe) { handle.leavePlayer(); break; } case 'OBJECT': case 'EMBED': case 'VIDEO': if (target.offsetWidth > 99 && target.offsetHeight > 99) { player = target; setButton.init(); } break; default: handle.leavePlayer(); } }, leavePlayer: function() { if (controlBtn.style.visibility == 'visible') { controlBtn.style.opacity = ''; controlBtn.style.visibility = ''; picinpicBtn.style.opacity = ''; picinpicBtn.style.visibility = ''; try { player.removeEventListener('mouseleave', handle.leavePlayer, false); } catch (e) {} document.removeEventListener('scroll', handle.scrollFix, false); } }, scrollFix: function(e) { clearTimeout(backStyle.scrollFixTimer); backStyle.scrollFixTimer = setTimeout(function() { setButton.locate(); }, 20); }, hotKey: function(e) { //默认退出键为ESC。需要修改为其他快捷键的请搜索"keycode",修改为按键对应的数字。 if (e.keyCode == 27) { maximize.playerControl(); } //默认画中画快捷键为F2。 if (e.keyCode == 113) { pictureInPicture(); } }, restoreButton: function() { if (isIframe) { return; } switch (browser) { case 'chrome': if (window.outerWidth < window.screen.width - 10) { setButton.show(); } break; case 'firefox': if (window.innerWidth < window.screen.width - 10) { setButton.show(); } break; } } }; var maximize = { playerControl: function() { if (!player) { return; } this.checkParent(); if (!fullStatus) { this.fullWin(); } else { this.smallWin(); } }, checkParent: function() { parentArray = []; var full = player; while (full = full.parentNode) { if (full.nodeName == 'BODY') { break; } if (full.getAttribute) { parentArray.push(full); } } }, fullWin: function() { if (!fullStatus) { document.removeEventListener('mouseover', handle.getPlayer, false); if (isRbtn) { try { player.addEventListener('mouseover', handle.restoreButton, false); } catch (e) { mouse.over = player.onmouseover; player.onmouseover = handle.restoreButton; } } backStyle = { htmlId: document.body.parentNode.id, bodyId: document.body.id }; if (document.location.hostname == 'www.youtube.com') { if (document.querySelector('#movie_player .ytp-size-button .ytp-svg-shadow').getBoundingClientRect().width == 20) { document.querySelector('.ytp-size-button').click(); backStyle.ytbStageChange = true; } } if (document.location.hostname == 'live.bilibili.com' && document.querySelector('.bilibili-live-player') && document.querySelector('.bilibili-live-player').getAttribute('data-player-state') != 'web-fullscreen') { unsafeWindow.$('.bilibili-live-player-video-danmaku').dblclick(); backStyle.biliPlayerChange = true; } if (document.location.hostname == 'v.youku.com' && document.querySelector('.vpactionv5_iframe_wrap') && tool.getRect(player).pageY + player.offsetHeight - tool.getRect(document.querySelector('.vpactionv5_iframe_wrap')).pageY > 20) { player.style.cssText = 'height: calc(100vh + 50px) !important;'; } if (document.location.hostname == 'www.tudou.com' && document.querySelector('.action_buttons.fix') && tool.getRect(player).pageY + player.offsetHeight - tool.getRect(document.querySelector('.action_buttons.fix')).pageY > 20) { player.style.cssText = 'height: calc(100vh + 55px) !important;'; } if (document.location.hostname == 'mp.weixin.qq.com' || document.location.hostname == 'www.doseeing.com') { player.style.cssText = ''; } leftBtn.style.display = 'block'; rightBtn.style.display = 'block'; controlBtn.style.display = ''; this.addClass(); } fullStatus = true; }, addClass: function() { document.body.parentNode.id = 'htmlToothbrush'; document.body.id = 'bodyToothbrush'; for (var i = 0; i < parentArray.length; i++) { parentArray[i].classList.add('parentToothbrush'); //父元素position:fixed会造成层级错乱 if (getComputedStyle(parentArray[i]).position == 'fixed') { parentArray[i].classList.add('absoluteToothbrush'); } } player.classList.add('playerToothbrush'); if (player.nodeName == 'VIDEO') { backStyle.controls = player.controls; player.controls = true; } window.dispatchEvent(new Event('resize')); }, smallWin: function() { if (isRbtn) { try { player.removeEventListener('mouseover', handle.restoreButton, false); } catch (e) {} if (mouse.over != 'listener') { player.onmouseover = mouse.over; } } document.body.parentNode.id = backStyle.htmlId; document.body.id = backStyle.bodyId; for (var i = 0; i < parentArray.length; i++) { parentArray[i].classList.remove('parentToothbrush'); parentArray[i].classList.remove('absoluteToothbrush'); } player.classList.remove('playerToothbrush'); if (document.location.hostname == 'www.youtube.com' && backStyle.ytbStageChange) { document.querySelector('.ytp-size-button').click(); backStyle.ytbStageChange = false; } if (document.location.hostname == 'live.bilibili.com' && backStyle.biliPlayerChange) { unsafeWindow.$('.bilibili-live-player-video-danmaku').dblclick(); } if (document.location.hostname == 'v.youku.com' || document.location.hostname == 'www.tudou.com') { player.style.cssText = ''; } if (player.nodeName == 'VIDEO') { player.controls = backStyle.controls; } leftBtn.style.display = ''; rightBtn.style.display = ''; controlBtn.style.display = ''; document.addEventListener('mouseover', handle.getPlayer, false); window.dispatchEvent(new Event('resize')); fullStatus = false; } }; var pictureInPicture = function() { if (!document.pictureInPictureElement) { if (player) { player.querySelector('video').requestPictureInPicture() .catch(error => {}); } else { document.querySelector('video').requestPictureInPicture() .catch(error => {}); } } else { document.exitPictureInPicture() .catch(error => {}); } } var init = function() { controlBtn = createButton('playerControlBtn'); picinpicBtn = document.createElement('tbdiv'); picinpicBtn.id = "picinpicBtn"; picinpicBtn.onclick = function() { pictureInPicture(); }; document.body.appendChild(picinpicBtn); leftBtn = createButton('leftFullStackButton'); rightBtn = createButton('rightFullStackButton'); if (getComputedStyle(controlBtn).position != 'fixed') { tool.addStyle([ '#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:1px !important;width:calc(100vw - 2px) !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:2147483647 !important;border:none !important;background-color:#000 !important;transform:none !important;}', '#htmlToothbrush #bodyToothbrush .playerToothbrush video {object-fit:contain !important;}', '#playerControlBtn {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;}', '#playerControlBtn.playerControlBtnCol {width:20px;height:64px;line-height:16px;}', '#picinpicBtn {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')); tool.addStyle([ //gimy.tv '#htmlToothbrush #bodyToothbrush #plyrplayer {height: 100vh !important;}', //weibo '#htmlToothbrush #bodyToothbrush .node-video.node-full video,#htmlToothbrush #bodyToothbrush .WB_h5video video {width: inherit !important;height: inherit !important;}', //douyu '#htmlToothbrush #bodyToothbrush #douyu_room_normal_flash_proxy_box {position:fixed !important;top:0px !important;left:1px !important;width:calc(100vw - 2px) !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:2147483645 !important;border:none !important;background-color:#000 !important;transform:none !important;}' ].join('\n')); } }; init(); document.addEventListener('mouseover', handle.getPlayer, false); document.addEventListener('keydown', handle.hotKey, false); })();