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.

当前为 2025-06-23 提交的版本,查看 最新版本

  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.3
  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. if (window.trustedTypes && window.trustedTypes.createPolicy) {
  24. window.trustedTypes.createPolicy("default", {
  25. createHTML: (string) => string,
  26.  
  27. createScriptURL: (string) => string,
  28.  
  29. createScript: (string) => string,
  30. });
  31. }
  32.  
  33. 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>`;
  34.  
  35. const defaultStyle = `.ytp-bezel { display: none !important; }`;
  36.  
  37. const toggleStyle = `
  38. .ytp-chrome-top, .ytp-gradient-top,
  39. .ytp-gradient-bottom, .ytp-chrome-bottom {
  40. display: none !important;
  41. }
  42. .caption-window, .caption-window.ytp-caption-window-bottom,
  43. .caption-window ytp-caption-window-top {
  44. margin-bottom: 0 !important;
  45. margin-top: 0 !important;
  46. }
  47. `;
  48.  
  49. const playIconContainerEleStyle = {
  50. position: "absolute",
  51. zIndex: 69,
  52. width: "100%",
  53. height: "0",
  54. bottom: "0",
  55. background: "red",
  56. };
  57.  
  58. const playIconEleStyle = {
  59. position: "absolute",
  60. right: "30px",
  61. bottom: "60px",
  62. };
  63.  
  64. let html5VideoPlayerEle = null;
  65. let html5MainVideoEle = null;
  66. let toggleStyleEle = null;
  67. let mouseMoveTimeoutId = null;
  68. const classNamesToCheckForHover = ["ytp-chrome-top", "ytp-chrome-bottom"];
  69. const playIconContainerEle = document.createElement("div");
  70. playIconContainerEle.innerHTML = playIconSVG;
  71. const playIconEle = playIconContainerEle.querySelector("svg");
  72.  
  73. Object.assign(playIconContainerEle.style, playIconContainerEleStyle);
  74. Object.assign(playIconEle.style, playIconEleStyle);
  75.  
  76. const addToggleStyleEle = () => {
  77. const isHover = isAnyElementHovered(classNamesToCheckForHover);
  78. if (isHover) return;
  79.  
  80. toggleStyleEle = GM_addStyle(toggleStyle);
  81. };
  82.  
  83. const addDefaultStyleEle = () => GM_addStyle(defaultStyle);
  84.  
  85. const removeToggleStyleEle = () => {
  86. toggleStyleEle?.parentNode?.removeChild(toggleStyleEle);
  87. toggleStyleEle = null;
  88. };
  89.  
  90. const isAnyElementHovered = (classNames) => {
  91. for (let className of classNames) {
  92. let elements = document.getElementsByClassName(className);
  93. for (let element of elements) {
  94. if (element.matches(":hover")) {
  95. return true;
  96. }
  97. }
  98. }
  99. return false;
  100. };
  101.  
  102. const handleMouseMoveEvent = () => {
  103. clearTimeout(mouseMoveTimeoutId);
  104. if (toggleStyleEle) removeToggleStyleEle();
  105. mouseMoveTimeoutId = setTimeout(addToggleStyleEle, 1000);
  106. };
  107.  
  108. const appendPlayIconContainerEle = () =>
  109. html5VideoPlayerEle.appendChild(playIconContainerEle);
  110.  
  111. const removePlayIconContainerEle = () =>
  112. html5VideoPlayerEle.removeChild(playIconContainerEle);
  113.  
  114. const initialHtml5MainVideoEleEvent = () => {
  115. html5MainVideoEle.addEventListener("play", () =>
  116. removePlayIconContainerEle(),
  117. );
  118. html5MainVideoEle.addEventListener("pause", () =>
  119. appendPlayIconContainerEle(),
  120. );
  121. };
  122.  
  123. const initializeElements = () => {
  124. html5VideoPlayerEle = document.querySelector(".html5-video-player");
  125. html5MainVideoEle = document.querySelector(".html5-main-video");
  126.  
  127. if (!html5VideoPlayerEle || !html5MainVideoEle) return;
  128. initialHtml5MainVideoEleEvent();
  129. clearInterval(initializeElementsIntervalId);
  130. };
  131.  
  132. let initializeElementsIntervalId = setInterval(initializeElements, 300);
  133.  
  134. window.addEventListener("load", () => {
  135. addDefaultStyleEle();
  136. });
  137.  
  138. window.addEventListener("mousemove", handleMouseMoveEvent);
  139. })();