Youtube: Hide Video

Make Youtube Video and Images Opacity Lower.

目前为 2020-04-13 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Youtube: Hide Video
  3. // @version 1.0.0
  4. // @description Make Youtube Video and Images Opacity Lower.
  5. // @author Hayao-Gai
  6. // @namespace https://github.com/HayaoGai
  7. // @icon https://upload.wikimedia.org/wikipedia/commons/4/4c/YouTube_icon.png
  8. // @include http*://www.youtube.com/*
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // ==/UserScript==
  12.  
  13. /* jshint esversion: 6 */
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. // Icons made by https://www.flaticon.com/authors/pixel-perfect
  19. const off1 = `<svg width="35" height="35" viewBox="0 -107 512 512"><path d="m362.667969 298.667969h-213.335938c-82.34375 0-149.332031-67.007813-149.332031-149.335938 0-82.324219 66.988281-149.332031 149.332031-149.332031h213.335938c82.34375 0 149.332031 67.007812 149.332031 149.332031 0 82.328125-66.988281 149.335938-149.332031 149.335938zm-213.335938-266.667969c-64.703125 0-117.332031 52.652344-117.332031 117.332031 0 64.683594 52.628906 117.335938 117.332031 117.335938h213.335938c64.703125 0 117.332031-52.652344 117.332031-117.335938 0-64.679687-52.628906-117.332031-117.332031-117.332031zm0 0"/><path d="m149.332031 234.667969c-47.058593 0-85.332031-38.273438-85.332031-85.335938 0-47.058593 38.273438-85.332031 85.332031-85.332031 47.0625 0 85.335938 38.273438 85.335938 85.332031 0 47.0625-38.273438 85.335938-85.335938 85.335938zm0-138.667969c-29.394531 0-53.332031 23.914062-53.332031 53.332031 0 29.421875 23.9375 53.335938 53.332031 53.335938 29.398438 0 53.335938-23.914063 53.335938-53.335938 0-29.417969-23.9375-53.332031-53.335938-53.332031zm0 0"/></svg>`;
  20. const off2 = `<svg width="35" height="35" viewBox="0 -107 512 512"><path d="m362.667969 0h-213.335938c-82.324219 0-149.332031 66.988281-149.332031 149.332031 0 82.347657 67.007812 149.335938 149.332031 149.335938h213.335938c82.324219 0 149.332031-66.988281 149.332031-149.335938 0-82.34375-67.007812-149.332031-149.332031-149.332031zm-213.335938 234.667969c-47.058593 0-85.332031-38.273438-85.332031-85.335938 0-47.058593 38.273438-85.332031 85.332031-85.332031 47.0625 0 85.335938 38.273438 85.335938 85.332031 0 47.0625-38.273438 85.335938-85.335938 85.335938zm0 0"/></svg>`;
  21. const on1 = `<svg width="35" height="35" viewBox="0 -107 512 512"><path d="m0 149.332031c0 82.347657 67.007812 149.335938 149.332031 149.335938h213.335938c82.324219 0 149.332031-66.988281 149.332031-149.335938 0-82.34375-67.007812-149.332031-149.332031-149.332031h-213.335938c-82.324219 0-149.332031 66.988281-149.332031 149.332031zm277.332031 0c0-47.058593 38.273438-85.332031 85.335938-85.332031 47.058593 0 85.332031 38.273438 85.332031 85.332031 0 47.0625-38.273438 85.335938-85.332031 85.335938-47.0625 0-85.335938-38.273438-85.335938-85.335938zm0 0"/></svg>`;
  22. const on2 = `<svg width="35" height="35" viewBox="0 -107 512 512"><path d="m362.667969 298.667969h-213.335938c-82.34375 0-149.332031-67.007813-149.332031-149.335938 0-82.324219 66.988281-149.332031 149.332031-149.332031h213.335938c82.34375 0 149.332031 67.007812 149.332031 149.332031 0 82.328125-66.988281 149.335938-149.332031 149.335938zm-213.335938-266.667969c-64.703125 0-117.332031 52.652344-117.332031 117.332031 0 64.683594 52.628906 117.335938 117.332031 117.335938h213.335938c64.703125 0 117.332031-52.652344 117.332031-117.335938 0-64.679687-52.628906-117.332031-117.332031-117.332031zm0 0"/><path d="m362.667969 234.667969c-47.0625 0-85.335938-38.273438-85.335938-85.335938 0-47.058593 38.273438-85.332031 85.335938-85.332031 47.058593 0 85.332031 38.273438 85.332031 85.332031 0 47.0625-38.273438 85.335938-85.332031 85.335938zm0-138.667969c-29.398438 0-53.335938 23.914062-53.335938 53.332031 0 29.421875 23.9375 53.335938 53.335938 53.335938 29.394531 0 53.332031-23.914063 53.332031-53.335938 0-29.417969-23.9375-53.332031-53.332031-53.332031zm0 0"/></svg>`;
  23.  
  24. defineCSS();
  25. window.onload = init;
  26. function init() {
  27. detectUrl();
  28. addButton();
  29. hideTarget("img", 0);
  30. hideTarget("video", 0);
  31. observeReady(0);
  32. }
  33.  
  34.  
  35.  
  36. function addButton() {
  37. // get
  38. const logo = isCurrent() ? document.querySelector("ytd-topbar-logo-renderer#logo:not(added)") : document.querySelector(".yt-masthead-logo-container:not(added)");
  39. logo.classList.add("added");
  40. // set
  41. const button = document.createElement("span");
  42. button.classList.add("switch");
  43. // dark theme
  44. const attDark = document.createAttribute("dark");
  45. attDark.value = isDark();
  46. button.setAttributeNode(attDark);
  47. // svg
  48. button.innerHTML = switchSVG();
  49. // append
  50. logo.parentNode.insertBefore(button, logo.nextSibling);
  51. // listener
  52. button.addEventListener("click", () => {
  53. setToggle(!getToggle());
  54. button.innerHTML = switchSVG();
  55. });
  56. }
  57.  
  58. function hideTarget(target, retry) {
  59. // get
  60. if (document.querySelectorAll(target).length === 0) {
  61. if (retry < 10) {
  62. retry++;
  63. setTimeout(() => hideTarget(target, retry), 500);
  64. return;
  65. } else {
  66. return;
  67. }
  68. }
  69. // set
  70. if (getToggle()) {
  71. document.querySelectorAll(target).forEach(t => t.classList.add("hide"));
  72. } else {
  73. document.querySelectorAll(target).forEach(t => t.classList.remove("hide"));
  74. }
  75. }
  76.  
  77. function manualDark() {
  78. const button = document.querySelector("span.switch");
  79. button.setAttribute("dark", window.location.href.includes("watch?v=") ? true : isDark());
  80. button.innerHTML = switchSVG();
  81. }
  82.  
  83.  
  84.  
  85. function setToggle(value) {
  86. GM_setValue("switch", value);
  87. hideTarget("img", 0);
  88. hideTarget("video", 0);
  89. }
  90.  
  91. function getToggle() {
  92. return GM_getValue("switch", false);
  93. }
  94.  
  95. function switchSVG() {
  96. const on = (!isDark() && !window.location.href.includes("watch?v=")) ? on1 : on2;
  97. const off = (!isDark() && !window.location.href.includes("watch?v=")) ? off1 : off2;
  98. return getToggle() ? on : off;
  99. }
  100.  
  101. function isCurrent() {
  102. if (!!document.querySelector(".yt-masthead-logo-container:not(added)")) {
  103. return false;
  104. } else {
  105. return true;
  106. }
  107. }
  108.  
  109. function isDark() {
  110. if (!isCurrent()) {
  111. return false;
  112. } else {
  113. return document.querySelector("html").getAttribute("dark");
  114. }
  115. }
  116.  
  117.  
  118.  
  119. function observeReady(retry) {
  120. const target1 = document.querySelector("html");
  121. const target2 = isCurrent ? document.querySelector("ytd-item-section-renderer#sections") : document.head;
  122. const target3 = document.querySelector("ytd-section-list-renderer");
  123. if (!target1 || (window.location.href.includes("watch?v=") && !target2)) {
  124. if (retry < 10) {
  125. retry++;
  126. setTimeout(() => observeReady(retry), 500);
  127. } else {
  128. console.log("Error: Can't get the specific node.");
  129. }
  130. } else {
  131. observeSystem(target1, target2);
  132. }
  133. }
  134.  
  135. function observeSystem(target1, target2) {
  136. const Mutation = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
  137. const observer1 = new Mutation(manualDark);
  138. const observer2 = new Mutation(() => hideTarget("img", 0));
  139. const config = { attributes: true, childList: true, characterData: true };
  140. if (target1) observer1.observe(target1, config);
  141. if (target2) observer2.observe(target2, config);
  142. }
  143.  
  144. function detectUrl() {
  145. window.addEventListener('locationchange', init);
  146. // situation 1
  147. history.pushState = ( f => function pushState(){
  148. var ret = f.apply(this, arguments);
  149. window.dispatchEvent(new Event('pushState'));
  150. window.dispatchEvent(new Event('locationchange'));
  151. return ret;
  152. })(history.pushState);
  153. // situation 2
  154. history.replaceState = ( f => function replaceState(){
  155. var ret = f.apply(this, arguments);
  156. window.dispatchEvent(new Event('replaceState'));
  157. window.dispatchEvent(new Event('locationchange'));
  158. return ret;
  159. })(history.replaceState);
  160. // situation 3
  161. window.addEventListener('popstate', () => window.dispatchEvent(new Event('locationchange')));
  162. }
  163.  
  164. function defineCSS() {
  165. const style = document.createElement("style");
  166. style.type = "text/css";
  167. style.innerHTML =
  168. `.switch {
  169. position: absolute;
  170. left: 190px;
  171. top: 8px;
  172. }
  173. .switch[dark="true"] {
  174. position: absolute;
  175. left: 190px;
  176. top: 8px;
  177. fill: white;
  178. }
  179. .hide {
  180. transition: opacity 0.3s;
  181. opacity: 0.1;
  182. }`;
  183. document.head.appendChild(style);
  184. }
  185.  
  186. })();

QingJ © 2025

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