视频网页全屏

让所有视频网页全屏

当前为 2017-11-04 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Maximize Video
  3. // @name:zh-CN 视频网页全屏
  4. // @namespace http://www.icycat.com
  5. // @description Maximize all video players
  6. // @description:zh-CN 让所有视频网页全屏
  7. // @author 冻猫
  8. // @include *
  9. // @exclude *www.w3school.com.cn*
  10. // @version 9.5.3
  11. // @grant unsafeWindow
  12. // @run-at document-end
  13. // ==/UserScript==
  14.  
  15. (function() {
  16.  
  17. 'use strict';
  18.  
  19. var fullStatus = false,
  20. isIframe = false,
  21. isFullIframePlayer = false,
  22. isRbtn = true,
  23. parentArray = new Array(),
  24. backStyle = new Object(),
  25. mouse = {
  26. leave: 'listener',
  27. over: 'listener'
  28. },
  29. browser, btnText, player, controlBtn, leftBtn, rightBtn;
  30.  
  31. //Html5规则[overlay|从overlay到player节点数或player节点],适用于自适应大小HTML5播放器
  32. var html5Rules = {
  33. 'pan.baidu.com': ['#video-root|#video-player'],
  34. 'www.nicovideo.jp': ['#UadPlayer|2'],
  35. 'thevideo.me': ['#vplayer video|1'],
  36. 'kimcartoon.me': ['#divContentVideo video|1'],
  37. 'www.dailymotion.com': ['#player video|4', '#player .dmp_VideoView|2'],
  38. 'v.youku.com': ['#ykPlayer .youku_layer_logo|3', '#ykPlayer .h5-layer-conatiner|2'],
  39. 'www.iqiyi.com': ['#flashbox video|2'],
  40. 'www.youtube.com': ['#player-api video|3', '#c4-player video|2', '#player-container video|3', '#movie_player|0'],
  41. 'www.twitch.tv': ['#player .js-control-fullscreen-overlay|1'],
  42. 'go.twitch.tv': ['#player .js-control-fullscreen-overlay|1'],
  43. 'www.huya.com': ['#player-video|3'],
  44. 'avgle.com': ['#video-player_html5_api|1', '#vjs-logobrand-image|2'],
  45. 'www.bilibili.com': ['#bilibiliPlayer video|4', '.bilibili-player-info|2'],
  46. 'www.pornhub.com': ['.mhp1138_eventCatcher|2'],
  47. 'www.redtube.com': ['.mhp1138_eventCatcher|1'],
  48. 'www.youporn.com': ['.mhp1138_eventCatcher|1'],
  49. 'www.icourse163.org': ['.ux-video-player .bbg|3'],
  50. 'www.panda.tv': ['#room-player-video-danmu div|3'],
  51. 'vk.com': ['.videoplayer_media|1'],
  52. 'www.douyu.com': ['.danmu-wrap video|2'],
  53. 'store.steampowered.com': ['#highlight_player_area video|2'],
  54. 'vimeo.com': ['.player .target|1'],
  55. 'ecchi.iwara.tv': ['#video-player video|1'],
  56. 'live.bilibili.com': ['.bilibili-live-player-video-danmaku|2', '.bilibili-live-player-video-gift|2'],
  57. 'v.qq.com': ['#tenvideo_player .txp_shadow|3', '#video_container_body .txp_shadow|3']
  58. };
  59.  
  60. //iframe播放器显示按钮规则
  61. //iframe关键字id、classname、src
  62. var iframeRules = /play|youtube\.com\/embed|video|movie|anime|flv|mp4|v\.youku\.com|www\.iqiyi\.com|v\.qq\.com|www\.le\.com/i;
  63. //网站域名
  64. var iframeUrlRules = [
  65. 'kisshentai.net',
  66. 'www.watchseries.ac',
  67. 'www.panda.tv',
  68. 'animeflv.net',
  69. 'www.vodlocker.city',
  70. 'projectwatchseries.com',
  71. 'reyanime.com'
  72. ];
  73.  
  74. //自动缩放内层内播放器规则
  75. var fullIframePlayerRules = [
  76. 'newplayer.jfrft.com',
  77. 'player.005.tv',
  78. 'player.xcmh.cc',
  79. 'www.auroravid.to',
  80. 'www.mp4upload.com',
  81. 'vodlocker.com',
  82. '52dongm.duapp.com'
  83. ];
  84.  
  85. //flash游戏页面,不在flash上显示还原按钮
  86. var excludeRbtnRules = [
  87. 'www.dmm.com',
  88. 'www.dmm.co.jp',
  89. 'www.4399.com',
  90. 'www.3366.com',
  91. 'flash.17173.com',
  92. 'www.7k7k.com'
  93. ];
  94.  
  95. if (excludeRbtnRules.indexOf(document.location.hostname) != -1) {
  96. isRbtn = false;
  97. }
  98.  
  99. if (window.top !== window.self) {
  100. isIframe = true;
  101. }
  102.  
  103. if (navigator.language.toLocaleLowerCase() == 'zh-cn') {
  104. btnText = {
  105. out: '网页全屏',
  106. inner: '内层全屏',
  107. restore: '还原大小'
  108. };
  109. } else {
  110. btnText = {
  111. out: 'Maximize',
  112. inner: 'M<br/>A<br/>X',
  113. restore: 'Restore'
  114. };
  115. }
  116.  
  117. if (/Firefox/i.test(navigator.userAgent)) {
  118. browser = 'firefox';
  119. } else if (/Chrome/i.test(navigator.userAgent)) {
  120. browser = 'chrome';
  121. } else {
  122. browser = 'other';
  123. }
  124.  
  125. var createButton = function(id) {
  126. var btn = document.createElement('tbdiv');
  127. btn.id = id;
  128. btn.onclick = function() {
  129. maximize.playerControl();
  130. };
  131. document.body.appendChild(btn);
  132. return btn;
  133. };
  134.  
  135. var tool = {
  136. getRect: function(element) {
  137. var rect = element.getBoundingClientRect();
  138. var scroll = tool.getScroll();
  139. return {
  140. pageX: rect.left + scroll.left,
  141. pageY: rect.top + scroll.top,
  142. screenX: rect.left,
  143. screenY: rect.top
  144. };
  145. },
  146. isFullClient: function(element) {
  147. var client = tool.getClient();
  148. var rect = tool.getRect(element);
  149. if (Math.abs(client.width - element.offsetWidth) < 21 && Math.abs(client.height - element.offsetHeight) < 21 && rect.screenY < 10 && rect.screenX < 20) {
  150. return true;
  151. } else {
  152. return false;
  153. }
  154. },
  155. isHtml5FullClient: function(element) {
  156. var client = tool.getClient();
  157. var rect = tool.getRect(element);
  158. var w = client.width - element.offsetWidth;
  159. var h = client.height - element.offsetHeight;
  160. if (w >= 0 && h >= 0) {
  161. if ((w < 21 && rect.screenX < 20) || (h < 21 && rect.screenY < 10)) {
  162. return true;
  163. } else {
  164. return false;
  165. }
  166. } else {
  167. return false;
  168. }
  169.  
  170. },
  171. getScroll: function() {
  172. return {
  173. left: document.documentElement.scrollLeft || document.body.scrollLeft,
  174. top: document.documentElement.scrollTop || document.body.scrollTop
  175. };
  176. },
  177. getClient: function() {
  178. return {
  179. width: document.compatMode == 'CSS1Compat' ? document.documentElement.clientWidth : document.body.clientWidth,
  180. height: document.compatMode == 'CSS1Compat' ? document.documentElement.clientHeight : document.body.clientHeight
  181. };
  182. },
  183. addStyle: function(css) {
  184. var style = document.createElement('style');
  185. style.type = 'text/css';
  186. var node = document.createTextNode(css);
  187. style.appendChild(node);
  188. document.head.appendChild(style);
  189. return style;
  190. }
  191. };
  192.  
  193. var setButton = {
  194. init: function() {
  195. //防止页面脚本干扰,重新初始化样式
  196. if (!document.getElementById('playerControlBtn')) {
  197. init();
  198. }
  199. if (isIframe && !isFullIframePlayer && fullIframePlayerRules.indexOf(document.location.hostname) != -1) {
  200. if (player.nodeName == 'OBJECT' || player.nodeName == 'EMBED') {
  201. maximize.checkParent();
  202. maximize.addClass();
  203. tool.addStyle('#htmlToothbrush #bodyToothbrush .playerToothbrush {left:0px !important;width:100vw !important;}');
  204. isFullIframePlayer = true;
  205. }
  206. }
  207. if (tool.isFullClient(player) || isFullIframePlayer) {
  208. return;
  209. }
  210. if (isIframe && player.nodeName == 'VIDEO' && tool.isHtml5FullClient(player)) {
  211. return;
  212. }
  213. this.show();
  214. },
  215. show: function() {
  216. try {
  217. player.addEventListener('mouseleave', handle.leavePlayer, false);
  218. } catch (e) {
  219. mouse.leave = player.onmouseleave;
  220. player.onmouseleave = function() {
  221. handle.leavePlayer();
  222. player.onmouseleave = mouse.leave;
  223. };
  224. }
  225. if (!fullStatus) {
  226. document.addEventListener('scroll', handle.scrollFix, false);
  227. }
  228. controlBtn.style.display = 'block';
  229. controlBtn.style.visibility = 'visible';
  230. this.locate();
  231. },
  232. locate: function() {
  233. var playerRect = tool.getRect(player);
  234. if (playerRect.pageY < 20 || fullStatus) {
  235. if (fullStatus) {
  236. controlBtn.classList.remove('playerControlBtnCol');
  237. playerRect.screenY = playerRect.screenY + 50;
  238. playerRect.screenX = playerRect.screenX - 30;
  239. controlBtn.innerHTML = btnText.restore;
  240. } else {
  241. playerRect.screenY = playerRect.screenY + 20;
  242. if (Math.abs(tool.getClient().width - player.offsetWidth) < 21 && Math.abs(tool.getClient().height - player.offsetHeight) > 21) {
  243. playerRect.screenX = playerRect.screenX + 44;
  244. } else {
  245. playerRect.screenX = playerRect.screenX + 64;
  246. }
  247. controlBtn.classList.add('playerControlBtnCol');
  248. if (isIframe) {
  249. controlBtn.innerHTML = btnText.inner;
  250. } else {
  251. controlBtn.innerHTML = btnText.out;
  252. }
  253. }
  254. if (browser == 'firefox' && fullStatus) {
  255. controlBtn.style.opacity = '1';
  256. } else {
  257. controlBtn.style.opacity = '0.5';
  258. }
  259. } else {
  260. controlBtn.classList.remove('playerControlBtnCol');
  261. controlBtn.style.opacity = '0.5';
  262. controlBtn.innerHTML = btnText.out;
  263. }
  264. controlBtn.style.top = playerRect.screenY - 20 + 'px';
  265. controlBtn.style.left = playerRect.screenX - 64 + player.offsetWidth + 'px';
  266. }
  267. };
  268.  
  269. var handle = {
  270. getPlayer: function(e) {
  271. if (fullStatus) {
  272. return;
  273. }
  274. var target = e.target;
  275. if (html5Rules[document.location.hostname]) {
  276. var overlay = [],
  277. playerNum = [];
  278. var overlayRules = html5Rules[document.location.hostname];
  279. for (var i = 0; i < overlayRules.length; i++) {
  280. var rules = overlayRules[i].split('|');
  281. overlay[i] = document.querySelector(rules[0]);
  282. playerNum[i] = rules[1];
  283. }
  284. if (overlay.indexOf(target) != -1) {
  285. var html5Player = target;
  286. if (!isNaN(Number(playerNum[overlay.indexOf(target)]))){
  287. for (var i = 0; i < playerNum[overlay.indexOf(target)]; i++) {
  288. html5Player = html5Player.parentNode;
  289. }
  290. } else {
  291. html5Player = document.querySelector(playerNum[overlay.indexOf(target)]);
  292. }
  293.  
  294. player = html5Player;
  295. setButton.init();
  296. return;
  297. }
  298. }
  299. switch (target.nodeName) {
  300. case 'IFRAME':
  301. if (!iframeRules.test(target.className) && !iframeRules.test(target.src) && !iframeRules.test(target.id) && !iframeRules.test(document.location.href) && iframeUrlRules.indexOf(document.location.hostname) == -1) {
  302. handle.leavePlayer();
  303. break;
  304. }
  305. case 'OBJECT':
  306. case 'EMBED':
  307. case 'VIDEO':
  308. if (target.offsetWidth > 99 && target.offsetHeight > 99) {
  309. player = target;
  310. setButton.init();
  311. }
  312. break;
  313. default:
  314. handle.leavePlayer();
  315. }
  316. },
  317. leavePlayer: function() {
  318. if (controlBtn.style.visibility == 'visible') {
  319. controlBtn.style.opacity = '';
  320. controlBtn.style.visibility = '';
  321. try {
  322. player.removeEventListener('mouseleave', handle.leavePlayer, false);
  323. } catch (e) {}
  324. document.removeEventListener('scroll', handle.scrollFix, false);
  325. }
  326. },
  327. scrollFix: function(e) {
  328. clearTimeout(backStyle.scrollFixTimer);
  329. backStyle.scrollFixTimer = setTimeout(function() {
  330. setButton.locate();
  331. }, 20);
  332. },
  333. hotKey: function(e) {
  334. //默认退出键为ESC。需要修改为其他快捷键的请搜索"keycode",修改为按键对应的数字。
  335. if (e.keyCode == 27) {
  336. maximize.playerControl();
  337. }
  338. },
  339. restoreButton: function() {
  340. if (isIframe) {
  341. return;
  342. }
  343. switch (browser) {
  344. case 'chrome':
  345. if (window.outerWidth < window.screen.width - 10) {
  346. setButton.show();
  347. }
  348. break;
  349. case 'firefox':
  350. if (window.innerWidth < window.screen.width - 10) {
  351. setButton.show();
  352. }
  353. break;
  354. }
  355. }
  356. };
  357.  
  358. var maximize = {
  359. playerControl: function() {
  360. if (!player) {
  361. return;
  362. }
  363. this.checkParent();
  364. if (!fullStatus) {
  365. this.fullWin();
  366. } else {
  367. this.smallWin();
  368. }
  369. },
  370. checkParent: function() {
  371. parentArray = [];
  372. var full = player;
  373. while (full = full.parentNode) {
  374. if (full.nodeName == 'BODY') {
  375. break;
  376. }
  377. if (full.getAttribute) {
  378. parentArray.push(full);
  379. }
  380. }
  381. },
  382. fullWin: function() {
  383. if (!fullStatus) {
  384. document.removeEventListener('mouseover', handle.getPlayer, false);
  385. if (isRbtn) {
  386. try {
  387. player.addEventListener('mouseover', handle.restoreButton, false);
  388. } catch (e) {
  389. mouse.over = player.onmouseover;
  390. player.onmouseover = handle.restoreButton;
  391. }
  392. }
  393. backStyle = {
  394. htmlId: document.body.parentNode.id,
  395. bodyId: document.body.id
  396. };
  397. if (document.location.hostname == 'www.youtube.com') {
  398. if (document.querySelector('ytd-watch.ytd-page-manager')){
  399. if (!document.querySelector('ytd-watch.ytd-page-manager').hasAttribute('theater-requested_')){
  400. document.querySelector('.ytp-size-button').click();
  401. backStyle.ytbStageChange = true;
  402. }
  403. }else if (!document.querySelector('.watch-stage-mode')) {
  404. document.querySelector('.ytp-size-button').click();
  405. backStyle.ytbStageChange = true;
  406. }
  407. }
  408. if (document.location.hostname == 'live.bilibili.com' && document.querySelector('.bilibili-live-player') && document.querySelector('.bilibili-live-player').getAttribute('data-player-state') != 'web-fullscreen') {
  409. unsafeWindow.$('.bilibili-live-player-video-danmaku').dblclick();
  410. backStyle.biliPlayerChange = true;
  411. }
  412. 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) {
  413. player.style.cssText = 'height: calc(100vh + 50px) !important;';
  414. }
  415. 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) {
  416. player.style.cssText = 'height: calc(100vh + 55px) !important;';
  417. }
  418. leftBtn.style.display = 'block';
  419. rightBtn.style.display = 'block';
  420. controlBtn.style.display = '';
  421. this.addClass();
  422. }
  423. fullStatus = true;
  424. },
  425. addClass: function() {
  426. document.body.parentNode.id = 'htmlToothbrush';
  427. document.body.id = 'bodyToothbrush';
  428. for (var i = 0; i < parentArray.length; i++) {
  429. parentArray[i].classList.add('parentToothbrush');
  430. //父元素position:fixed会造成层级错乱
  431. if (getComputedStyle(parentArray[i]).position == 'fixed') {
  432. parentArray[i].classList.add('absoluteToothbrush');
  433. }
  434. }
  435. player.classList.add('playerToothbrush');
  436. if (player.nodeName == 'VIDEO') {
  437. backStyle.controls = player.controls;
  438. player.controls = true;
  439. }
  440. window.dispatchEvent(new Event('resize'));
  441. },
  442. smallWin: function() {
  443. if (isRbtn) {
  444. try {
  445. player.removeEventListener('mouseover', handle.restoreButton, false);
  446. } catch (e) {}
  447. if (mouse.over != 'listener') {
  448. player.onmouseover = mouse.over;
  449. }
  450. }
  451. document.body.parentNode.id = backStyle.htmlId;
  452. document.body.id = backStyle.bodyId;
  453. for (var i = 0; i < parentArray.length; i++) {
  454. parentArray[i].classList.remove('parentToothbrush');
  455. parentArray[i].classList.remove('absoluteToothbrush');
  456. }
  457. player.classList.remove('playerToothbrush');
  458. if (document.location.hostname == 'www.youtube.com' && backStyle.ytbStageChange) {
  459. document.querySelector('.ytp-size-button').click();
  460. }
  461. if (document.location.hostname == 'live.bilibili.com' && backStyle.biliPlayerChange) {
  462. unsafeWindow.$('.bilibili-live-player-video-danmaku').dblclick();
  463. }
  464. if (document.location.hostname == 'v.youku.com' || document.location.hostname == 'www.tudou.com') {
  465. player.style.cssText = '';
  466. }
  467. if (player.nodeName == 'VIDEO') {
  468. player.controls = backStyle.controls;
  469. }
  470. leftBtn.style.display = '';
  471. rightBtn.style.display = '';
  472. controlBtn.style.display = '';
  473. document.addEventListener('mouseover', handle.getPlayer, false);
  474. window.dispatchEvent(new Event('resize'));
  475. fullStatus = false;
  476. }
  477. };
  478.  
  479. var init = function() {
  480. controlBtn = createButton('playerControlBtn');
  481. leftBtn = createButton('leftFullStackButton');
  482. rightBtn = createButton('rightFullStackButton');
  483. if (getComputedStyle(controlBtn).position != 'fixed') {
  484. tool.addStyle([
  485. '#htmlToothbrush, #bodyToothbrush {overflow:hidden !important;zoom:100% !important}',
  486. '#htmlToothbrush #bodyToothbrush .parentToothbrush {overflow:visible !important;z-index:auto !important;transform:none !important;-webkit-transform-style:flat !important;transition:none !important;contain:none !important;}',
  487. '#htmlToothbrush #bodyToothbrush .absoluteToothbrush {position:absolute !important;}',
  488. '#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:2147483645 !important;border:none !important;background-color:#000 !important;transform:none !important;}',
  489. '#htmlToothbrush #bodyToothbrush .playerToothbrush video {object-fit:contain !important;}',
  490. '#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:2147483646;background-color: #27A9D8;color: #FFF;} #playerControlBtn:hover {visibility:visible;opacity:1;background-color:#2774D8;}',
  491. '#playerControlBtn.playerControlBtnCol {width:20px;height:64px;line-height:16px;}',
  492. '#leftFullStackButton{display:none;position:fixed;width:1px;height:100vh;top:0;left:0;z-index:2147483646;background:#000;}',
  493. '#rightFullStackButton{display:none;position:fixed;width:1px;height:100vh;top:0;right:0;z-index:2147483646;background:#000;}'
  494. ].join('\n'));
  495. }
  496. };
  497.  
  498. init();
  499.  
  500. document.addEventListener('mouseover', handle.getPlayer, false);
  501. document.addEventListener('keydown', handle.hotKey, false);
  502.  
  503. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址