视频网页全屏

让所有视频网页全屏

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

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

QingJ © 2025

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