YouTube Rotate 90°

把Youtube影片旋轉0°、90°、180°、270°,讓你輕鬆觀看影片!

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

  1. // ==UserScript==
  2. // @name YouTube Rotate 90°
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.7
  5. // @description 把Youtube影片旋轉0°、90°、180°、270°,讓你輕鬆觀看影片!
  6. // @author zaqwsx2205
  7. // @match https://*.youtube.com/*
  8. // @match https://*.youtube.com/watch?v=*
  9. // @match https://www.youtube.com/embed/*
  10. // @match https://www.youtube-nocookie.com/embed/*
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. (function () {
  15. 'use strict';
  16.  
  17. var click = 0;
  18. var safeURL = location.href;
  19. var svgicon = `<svg version="1.1" x="0px" y="0px" viewBox="0 0 453.227 453.227" style="enable-background:new 0 0 453.227 453.227;" xml:space="preserve" width="50%" height="100%" class=""><g><g><g><g><path d="M139.453,120.747L1.107,259.093L139.453,397.44L277.8,259.093L139.453,120.747z M61.373,259.093l77.973-77.973 l78.08,77.973l-77.973,77.973L61.373,259.093z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#FFFFFF"/><path d="M395.88,125.44C358.333,88,309.267,69.227,260.093,69.227V0l-90.56,90.56l90.56,90.453v-69.12 c38.187,0,76.48,14.613,105.6,43.733c58.347,58.347,58.347,152.853,0,211.2c-29.12,29.12-67.413,43.733-105.6,43.733 c-20.693,0-41.28-4.373-60.48-12.907l-31.787,31.787c28.587,15.787,60.373,23.787,92.267,23.787 c49.173,0,98.24-18.773,135.787-56.213C470.867,322.027,470.867,200.427,395.88,125.44z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#FFFFFF"/></g></g></g></g> </svg>`;
  20.  
  21. if (window.trustedTypes && window.trustedTypes.createPolicy && !window.trustedTypes.defaultPolicy) {
  22. window.trustedTypes.createPolicy('default', {
  23. createHTML: string => string
  24. });
  25. }
  26.  
  27. buildHTML();
  28. observeURL();
  29.  
  30. function buildHTML() {
  31. document.querySelectorAll('.video-div, .video-div1, .video-div2, .transform90').forEach(function (element) {
  32. element.remove();
  33. });
  34.  
  35. let container = document.body;
  36. let div = document.createElement('div');
  37. div.classList.add('video-div2');
  38. container.appendChild(div);
  39. div.innerHTML = `<style>
  40. .ytp-autohide .transform90-top {
  41. opacity: 0 !important;
  42. -moz-transition: opacity .1s cubic-bezier(0.4,0.0,1,1) !important;
  43. -webkit-transition: opacity .1s cubic-bezier(0.4,0.0,1,1) !important;
  44. transition: opacity .1s cubic-bezier(0.4,0.0,1,1) !important;
  45. }
  46. .ytp-transform90-icon {
  47. margin: auto !important;
  48. width: 36px !important;
  49. height: 36px !important;
  50. position: relative !important;
  51. }
  52. .ytp-big-mode .ytp-transform90-icon {
  53. width: 54px !important;
  54. height: 54px !important;
  55. }
  56. .ytp-transform90-title {
  57. font-weight: 500 !important;
  58. text-align: center !important;
  59. font-size: 14px !important;
  60. }
  61. .ytp-big-mode .ytp-transform90-title {
  62. font-size: 20px !important;
  63. }
  64. .ytp-miniplayer-scrim .transform90-miniplayer{
  65. position: absolute;
  66. width: 60px;
  67. height: 40px;
  68. padding: 8px;
  69. z-index: 67;
  70. top: 0;
  71. left: 40px;
  72. }
  73. </style>`;
  74.  
  75. if (document.querySelectorAll('.ytp-embed').length > 0) {
  76. let chromeTopButtons = document.querySelector('.ytp-chrome-top-buttons');
  77. let button = document.createElement('button');
  78. button.classList.add('ytp-button', 'transform90', 'transform90-top');
  79. button.setAttribute('data-tooltip-opaque', 'true');
  80. button.setAttribute('aria-label', '');
  81. button.style.width = 'auto';
  82. button.style.height = 'auto';
  83.  
  84. let iconDiv = document.createElement('div');
  85. iconDiv.classList.add('ytp-transform90-icon');
  86. iconDiv.style.transform = 'scaleX(-1)';
  87. iconDiv.innerHTML = `${svgicon}`;
  88.  
  89. let titleDiv = document.createElement('div');
  90. titleDiv.classList.add('ytp-transform90-title');
  91. titleDiv.textContent = 'Video Rotate 90°';
  92.  
  93. button.appendChild(iconDiv);
  94. button.appendChild(titleDiv);
  95.  
  96. chromeTopButtons.prepend(button);
  97. } else if (document.querySelector('.ytd-miniplayer #player-container #ytd-player')) {
  98. let scrim = document.querySelector('.ytp-miniplayer-scrim');
  99. let button = document.createElement('button');
  100. button.classList.add('transform90', 'ytp-play-button', 'ytp-button', 'transform90-miniplayer');
  101. button.title = 'Video Rotate 90°';
  102. button.setAttribute('aria-label', 'Video Rotate 90°');
  103. button.style.display = 'inline-flex';
  104. button.style.justifyContent = 'center';
  105. button.style.transform = 'scaleX(-1)';
  106. button.innerHTML = `${svgicon}`;
  107.  
  108. scrim.prepend(button);
  109. } else {
  110. let chromeControls = document.querySelector('.ytp-chrome-controls .ytp-right-controls');
  111. if (chromeControls != null) {
  112. let button = document.createElement('button');
  113. button.classList.add('transform90', 'ytp-button');
  114. button.title = 'Video Rotate 90°';
  115. button.setAttribute('aria-label', 'Video Rotate 90°');
  116. button.style.display = 'inline-flex';
  117. button.style.justifyContent = 'center';
  118. button.style.transform = 'scaleX(-1)';
  119. button.innerHTML = `${svgicon}`;
  120.  
  121. chromeControls.prepend(button);
  122. }
  123. }
  124.  
  125. document.querySelectorAll('.transform90').forEach(function (button) {
  126. button.addEventListener('click', function () {
  127. click++;
  128. transform(click);
  129. });
  130. });
  131. }
  132.  
  133.  
  134. function transform(x) {
  135. document.querySelectorAll('.video-div, .video-div1').forEach(function (el) {
  136. el.remove();
  137. });
  138.  
  139. switch (x) {
  140. case 1:
  141. addVideoRotateStyles(90);
  142. transform90();
  143. break;
  144. case 2:
  145. addVideoRotateStyles(180);
  146. break;
  147. case 3:
  148. addVideoRotateStyles(270);
  149. transform90();
  150. break;
  151. case 4:
  152. click = 0;
  153. break;
  154. }
  155. }
  156.  
  157. function addVideoRotateStyles(degrees) {
  158. var container = document.querySelector('.html5-video-container');
  159. var videoDiv = document.createElement('div');
  160. var videoDiv1 = document.createElement('div');
  161.  
  162. videoDiv.className = 'video-div';
  163. videoDiv1.className = 'video-div1';
  164.  
  165. container.appendChild(videoDiv);
  166. container.appendChild(videoDiv1);
  167.  
  168. var styleContent = `
  169. .html5-video-container {
  170. display: flex !important;
  171. justify-content: center !important;
  172. align-items: center !important;
  173. height: 100% !important;
  174. }
  175. .video-stream {
  176. position: relative !important;
  177. transform: rotate(${degrees}deg) !important;
  178. height: auto !important;
  179. left: 0 !important;
  180. top: 0 !important;
  181. }
  182. `;
  183.  
  184. videoDiv.innerHTML = `<style>${styleContent}</style>`;
  185. }
  186.  
  187. function transform90() {
  188. setTimeout(function () {
  189. var container = document.querySelector('.html5-video-container');
  190. var width = container.offsetWidth;
  191. var height = container.offsetHeight;
  192. var wh = width - height;
  193. var videoDiv1 = document.querySelector('.video-div1');
  194.  
  195. if (videoDiv1) {
  196. videoDiv1.innerHTML = '<style>.video-stream{width:calc(100% - ' + wh + 'px)!important;}</style>';
  197. }
  198. }, 20);
  199. }
  200.  
  201. function observeURL() {
  202. var composeBox = document.querySelector('#player-container video');
  203. var composeObserver = new MutationObserver(function (mutationsList) {
  204. if (safeURL !== location.href) {
  205. safeURL = location.href;
  206. click = 0;
  207. buildHTML();
  208. }
  209. });
  210.  
  211. if (!composeBox) {
  212. window.setTimeout(observeURL, 500);
  213. return;
  214. }
  215.  
  216. var config = { characterData: true, childList: true, attributes: true };
  217. composeObserver.observe(composeBox, config);
  218. }
  219.  
  220. window.addEventListener('resize', function () {
  221. transform(click);
  222. });
  223.  
  224. document.addEventListener("fullscreenchange", function (event) {
  225. transform(click);
  226. });
  227.  
  228. /*document.querySelectorAll(".ytp-size-button").forEach(function (element) {
  229. element.addEventListener('click', function () {
  230. transform(click);
  231. });
  232. });*/
  233.  
  234. })();