Zoom function for YouTube

YouTube video zoom feature

  1. "use strict";
  2. // ==UserScript==
  3. // @name Zoom function for YouTube
  4. // @name:ja YouTubeで動画をズーム
  5. // @description YouTube video zoom feature
  6. // @description:ja YouTubeの動画プレイヤーにズーム機能を追加します
  7. // @version 2.0.3
  8. // @include /https?:\/\/www\.youtube\.com.*/
  9. // @author sititou70
  10. // @namespace https://github.com/sititou70/
  11. // @run-at document-idle
  12. // @license MIT; https://opensource.org/licenses/MIT
  13. // ==/UserScript==
  14. (function () {
  15. // consts
  16. var SCRIPT_NAME = 'youtube video zoom';
  17. var VIDEO_CONTAINER_SELECTOR = '#movie_player';
  18. var VIDEO_SELECTOR = VIDEO_CONTAINER_SELECTOR + " video";
  19. // functions
  20. var getScaleFromVideo = function (video) {
  21. var scale_string = video.style.transform.match(/scale\((.+?)\)/);
  22. if (scale_string === null)
  23. return 1;
  24. var scale = parseFloat(scale_string[1]);
  25. if (isNaN(scale))
  26. return 1;
  27. return scale;
  28. };
  29. var zoomVideoToRect = function (video, rect) {
  30. var video_scale = getScaleFromVideo(video);
  31. var video_client_rect = video.getBoundingClientRect();
  32. var video_rect = {
  33. width: video_client_rect.width / video_scale,
  34. height: video_client_rect.height / video_scale,
  35. };
  36. var player_aspect_ratio = video_rect.width / video_rect.height;
  37. var selected_aspect_ratio = rect.width / rect.height;
  38. var fit_width = player_aspect_ratio < selected_aspect_ratio; // or height?
  39. var scale = fit_width
  40. ? video_rect.width / rect.width
  41. : video_rect.height / rect.height;
  42. video.style.transform = "translateX(" + (video_rect.width / 2 - (rect.top_left.x + rect.width / 2)) * scale + "px) translateY(" + (video_rect.height / 2 - (rect.top_left.y + rect.height / 2)) * scale + "px) scale(" + scale + ")";
  43. video.style.transition = 'all 0.3s ease';
  44. };
  45. var drag_start_position;
  46. var handleDragStart = function (e) {
  47. var video = e.target;
  48. var video_rect = video.getBoundingClientRect();
  49. var scale = getScaleFromVideo(video);
  50. drag_start_position = {
  51. x: (e.clientX - video_rect.x) / scale,
  52. y: (e.clientY - video_rect.y) / scale,
  53. };
  54. };
  55. var handleDragEnd = function (e) {
  56. var video = e.target;
  57. var video_rect = video.getBoundingClientRect();
  58. var scale = getScaleFromVideo(video);
  59. var drag_end_position = {
  60. x: (e.clientX - video_rect.x) / scale,
  61. y: (e.clientY - video_rect.y) / scale,
  62. };
  63. var top_left = {
  64. x: Math.min(drag_start_position.x, drag_end_position.x),
  65. y: Math.min(drag_start_position.y, drag_end_position.y),
  66. };
  67. var bottom_right = {
  68. x: Math.max(drag_start_position.x, drag_end_position.x),
  69. y: Math.max(drag_start_position.y, drag_end_position.y),
  70. };
  71. var selected_rect = {
  72. top_left: top_left,
  73. bottom_right: bottom_right,
  74. width: bottom_right.x - top_left.x,
  75. height: bottom_right.y - top_left.y,
  76. };
  77. if (selected_rect.width <= 10 || selected_rect.height <= 10)
  78. return;
  79. zoomVideoToRect(video, selected_rect);
  80. video.click();
  81. };
  82. var setupZoomFeature = function () {
  83. var video = document.querySelector(VIDEO_SELECTOR);
  84. if (video === null)
  85. return;
  86. video.addEventListener('mousedown', handleDragStart);
  87. video.addEventListener('mouseup', handleDragEnd);
  88. };
  89. var onKeyPress = function (e) {
  90. var video = document.querySelector(VIDEO_SELECTOR);
  91. if (video === null)
  92. return;
  93. if (e.key === 'r')
  94. video.style.transform = '';
  95. };
  96. // main
  97. var main = function () {
  98. var document_observer = new MutationObserver(setupZoomFeature);
  99. document_observer.observe(document.body, {
  100. attributes: true,
  101. });
  102. document.addEventListener('keypress', onKeyPress);
  103. };
  104. console.log("[" + SCRIPT_NAME + "] loaded.");
  105. main();
  106. })();