YouTube Fullscreen Enhancer

This script enhances the user experience when pausing a YouTube video in full-screen mode by hiding certain elements and adding a play icon.

当前为 2024-03-28 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube Fullscreen Enhancer
  3. // @description This script enhances the user experience when pausing a YouTube video in full-screen mode by hiding certain elements and adding a play icon.
  4. // @author Wanten
  5. // @copyright 2024 Wanten
  6. // @license MIT
  7. // @supportURL https://github.com/WantenMN/youtube-fullscreen-enhancer/issues
  8. // @icon https://youtube.com/favicon.ico
  9. // @homepageURL https://github.com/WantenMN/youtube-fullscreen-enhancer
  10. // @namespace https://greasyfork.org/en/scripts/460569
  11. // @version 0.2.2
  12. // @match http*://*.youtube.com/*
  13. // @match http*://youtube.com/*
  14. // @match http*://*.youtu.be/*
  15. // @match http*://youtu.be/*
  16. // @run-at document-end
  17. // @grant GM_addStyle
  18. // ==/UserScript==
  19.  
  20. (function () {
  21. "use strict";
  22.  
  23. const playIconSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 24 24"><path fill="#e01b24" d="M21.593 7.203a2.506 2.506 0 0 0-1.762-1.766C18.265 5.007 12 5 12 5s-6.264-.007-7.831.404a2.56 2.56 0 0 0-1.766 1.778c-.413 1.566-.417 4.814-.417 4.814s-.004 3.264.406 4.814c.23.857.905 1.534 1.763 1.765c1.582.43 7.83.437 7.83.437s6.265.007 7.831-.403a2.515 2.515 0 0 0 1.767-1.763c.414-1.565.417-4.812.417-4.812s.02-3.265-.407-4.831M9.996 15.005l.005-6l5.207 3.005z"/></svg>`;
  24.  
  25. const defaultStyle = `.ytp-bezel { display: none !important; }`;
  26.  
  27. const toggleStyle = `
  28. .ytp-chrome-top, .ytp-gradient-top,
  29. .ytp-gradient-bottom, .ytp-chrome-bottom {
  30. display: none !important;
  31. }
  32. .caption-window, .caption-window.ytp-caption-window-bottom,
  33. .caption-window ytp-caption-window-top {
  34. margin-bottom: 0 !important;
  35. margin-top: 0 !important;
  36. }
  37. `;
  38.  
  39. const playIconContainerEleStyle = {
  40. position: "absolute",
  41. zIndex: 69,
  42. width: "100%",
  43. height: "0",
  44. bottom: "0",
  45. background: "red",
  46. };
  47.  
  48. const playIconEleStyle = {
  49. position: "absolute",
  50. right: "30px",
  51. bottom: "60px",
  52. };
  53.  
  54. let html5VideoPlayerEle = null;
  55. let html5MainVideoEle = null;
  56. let toggleStyleEle = null;
  57. let mouseMoveTimeoutId = null;
  58. const classNamesToCheckForHover = ["ytp-chrome-top", "ytp-chrome-bottom"];
  59. const playIconContainerEle = document.createElement("div");
  60. playIconContainerEle.innerHTML = playIconSVG;
  61. const playIconEle = playIconContainerEle.querySelector("svg");
  62.  
  63. Object.assign(playIconContainerEle.style, playIconContainerEleStyle);
  64. Object.assign(playIconEle.style, playIconEleStyle);
  65.  
  66. const addToggleStyleEle = () => {
  67. const isHover = isAnyElementHovered(classNamesToCheckForHover);
  68. if (isHover) return;
  69.  
  70. toggleStyleEle = GM_addStyle(toggleStyle);
  71. };
  72.  
  73. const addDefaultStyleEle = () => GM_addStyle(defaultStyle);
  74.  
  75. const removeToggleStyleEle = () => {
  76. toggleStyleEle?.parentNode?.removeChild(toggleStyleEle);
  77. toggleStyleEle = null;
  78. };
  79.  
  80. const isAnyElementHovered = (classNames) => {
  81. for (let className of classNames) {
  82. let elements = document.getElementsByClassName(className);
  83. for (let element of elements) {
  84. if (element.matches(":hover")) {
  85. return true;
  86. }
  87. }
  88. }
  89. return false;
  90. };
  91.  
  92. const handleMouseMoveEvent = () => {
  93. clearTimeout(mouseMoveTimeoutId);
  94. if (toggleStyleEle) removeToggleStyleEle();
  95. mouseMoveTimeoutId = setTimeout(addToggleStyleEle, 1000);
  96. };
  97.  
  98. const appendPlayIconContainerEle = () =>
  99. html5VideoPlayerEle.appendChild(playIconContainerEle);
  100.  
  101. const removePlayIconContainerEle = () =>
  102. html5VideoPlayerEle.removeChild(playIconContainerEle);
  103.  
  104. const initialHtml5MainVideoEleEvent = () => {
  105. html5MainVideoEle.addEventListener("play", () =>
  106. removePlayIconContainerEle()
  107. );
  108. html5MainVideoEle.addEventListener("pause", () =>
  109. appendPlayIconContainerEle()
  110. );
  111. };
  112.  
  113. const initializeElements = () => {
  114. html5VideoPlayerEle = document.querySelector(".html5-video-player");
  115. html5MainVideoEle = document.querySelector(".html5-main-video");
  116.  
  117. if (!html5VideoPlayerEle || !html5MainVideoEle) return;
  118. initialHtml5MainVideoEleEvent();
  119. clearInterval(initializeElementsIntervalId);
  120. };
  121.  
  122. let initializeElementsIntervalId = setInterval(initializeElements, 300);
  123.  
  124. window.addEventListener("load", () => {
  125. addDefaultStyleEle();
  126. });
  127.  
  128. window.addEventListener("mousemove", handleMouseMoveEvent);
  129. })();