视频网页全屏

让所有视频网页全屏

当前为 2017-05-07 提交的版本,查看 最新版本

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

QingJ © 2025

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