视频网页全屏

让所有视频网页全屏

当前为 2018-04-12 提交的版本,查看 最新版本

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

QingJ © 2025

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