Zoom on Hover

Zoom on Hover enlarges images when you hover over them.

目前为 2024-11-27 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Zoom on Hover
  3. // @name:es Zoom on Hover
  4. // @version 1.6.0
  5. // @description Zoom on Hover enlarges images when you hover over them.
  6. // @description:es Zoom on Hover amplía las imágenes cuando pasas el cursor sobre ellas.
  7. // @author Adam Jensen
  8. // @match *://*/*
  9. // @grant GM_addStyle
  10. // @license MIT
  11. // @namespace https://greasyfork.org/users/1398884
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. // Configuration
  18. const MAX_WIDTH = 500; // Maximum width of the enlarged image
  19. const MAX_HEIGHT = 500; // Maximum height of the enlarged image
  20. const ZOOM_FACTOR = 3; // Zoom factor (1x, 1.5x, 2x, 3x, etc)
  21. const MAX_SIZE = 800; // Maximum size in pixels (If an image has width or height greater than or equal to MAX_SIZE, it won't be enlarged)
  22. const MIN_SIZE = 50; // Minimum size in pixels (Images smaller than this size won't be enlarged)
  23. const MAX_DISPLAY_TIME = 10; // Maximum duration (in seconds) for how long the enlarged image stays visible
  24.  
  25. // Styles
  26. GM_addStyle(`
  27. .ampliar-img-flotante {
  28. position: absolute;
  29. z-index: 9999;
  30. border: 2px solid #ccc;
  31. background: rgba(255, 255, 255, 0.9);
  32. box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
  33. display: none;
  34. padding: 0px;
  35. pointer-events: none;
  36. height: auto;
  37. width: auto;
  38. box-sizing: border-box;
  39. }
  40. .ampliar-img-flotante img {
  41. width: 100%;
  42. height: 100%;
  43. object-fit: contain;
  44. display: block;
  45. margin: 0;
  46. box-sizing: border-box;
  47. }
  48. `);
  49.  
  50. // Create the floating window
  51. const ventanaFlotante = document.createElement('div');
  52. ventanaFlotante.classList.add('ampliar-img-flotante');
  53. const imagenFlotante = document.createElement('img');
  54. ventanaFlotante.appendChild(imagenFlotante);
  55. document.body.appendChild(ventanaFlotante);
  56.  
  57. let timer; // To store the timeout for hiding the floating window
  58.  
  59. // Function to enlarge the image with the zoom factor
  60. const ampliarImagen = (event) => {
  61. const target = event.target;
  62.  
  63. let imgSrc = '';
  64.  
  65. if (target.tagName === 'IMG') {
  66. // If the element is an <img>, use the src attribute
  67. imgSrc = target.src;
  68.  
  69. // Skip images with "logo" or "icon" in the alt attribute
  70. const altText = target.alt ? target.alt.toLowerCase() : '';
  71. if (altText.includes('logo') || altText.includes('icon')) {
  72. return;
  73. }
  74.  
  75. } else if (target.style.backgroundImage) {
  76. // If the element has a background image, extract the URL
  77. imgSrc = target.style.backgroundImage.replace(/^url\(["']?/, '').replace(/["']?\)$/, '');
  78. }
  79.  
  80. // Skip images from unwanted sources
  81. if (!imgSrc || imgSrc.includes('youtube.com') || imgSrc.includes('gstatic.com')) {
  82. return;
  83. }
  84.  
  85. // If the current image is the same as the previous one, return
  86. if (imagenFlotante.src === imgSrc) {
  87. return;
  88. }
  89.  
  90. // Hide the floating window if an image is already displayed
  91. if (ventanaFlotante.style.display === 'block') {
  92. ocultarVentanaFlotante(); // Hide and reset
  93. }
  94.  
  95. const img = new Image();
  96. img.onload = () => {
  97. // Don't enlarge images that are already large enough
  98. if (img.width >= MAX_SIZE || img.height >= MAX_SIZE) {
  99. return;
  100. }
  101.  
  102. // Don't enlarge images that are too small
  103. if (img.width < MIN_SIZE || img.height < MIN_SIZE) {
  104. return;
  105. }
  106.  
  107. const widthWithZoom = img.width * ZOOM_FACTOR;
  108. const heightWithZoom = img.height * ZOOM_FACTOR;
  109.  
  110. let finalWidth, finalHeight;
  111.  
  112. if (img.width > img.height) {
  113. finalWidth = Math.min(widthWithZoom, MAX_WIDTH);
  114. finalHeight = (img.height * finalWidth) / img.width;
  115. if (finalHeight > MAX_HEIGHT) {
  116. finalHeight = MAX_HEIGHT;
  117. finalWidth = (img.width * finalHeight) / img.height;
  118. }
  119. } else {
  120. finalHeight = Math.min(heightWithZoom, MAX_HEIGHT);
  121. finalWidth = (img.width * finalHeight) / img.height;
  122. if (finalWidth > MAX_WIDTH) {
  123. finalWidth = MAX_WIDTH;
  124. finalHeight = (img.height * finalWidth) / img.width;
  125. }
  126. }
  127.  
  128. imagenFlotante.src = imgSrc;
  129. ventanaFlotante.style.display = 'block';
  130. ventanaFlotante.style.width = `${finalWidth}px`;
  131. ventanaFlotante.style.height = `${finalHeight}px`;
  132.  
  133. // Calculate the position of the floating window
  134. const { top, left, width, height } = target.getBoundingClientRect();
  135. let newTop = top + window.scrollY;
  136. let newLeft = left + width + window.scrollX;
  137.  
  138. const viewportWidth = window.innerWidth;
  139. const viewportHeight = window.innerHeight;
  140.  
  141. // Adjust the position to avoid overflow to the right
  142. if (newLeft + ventanaFlotante.offsetWidth > viewportWidth) {
  143. newLeft = left - ventanaFlotante.offsetWidth + window.scrollX;
  144. }
  145.  
  146. // Adjust the position to avoid overflow to the bottom
  147. if (newTop + ventanaFlotante.offsetHeight > viewportHeight + window.scrollY) {
  148. newTop = top + height + window.scrollY - ventanaFlotante.offsetHeight;
  149. }
  150.  
  151. // Adjust the position to avoid overflow to the top
  152. if (newTop < window.scrollY) {
  153. newTop = window.scrollY;
  154. }
  155.  
  156. ventanaFlotante.style.top = `${newTop}px`;
  157. ventanaFlotante.style.left = `${newLeft}px`;
  158.  
  159. // Set a timer to automatically hide the floating window after MAX_DISPLAY_TIME
  160. clearTimeout(timer); // Clear any previous timer
  161. timer = setTimeout(ocultarVentanaFlotante, MAX_DISPLAY_TIME * 1000); // Hide after MAX_DISPLAY_TIME seconds
  162. };
  163. img.src = imgSrc;
  164. };
  165.  
  166. // Hide the floating window and reset the image source
  167. const ocultarVentanaFlotante = () => {
  168. ventanaFlotante.style.display = 'none';
  169. imagenFlotante.src = ''; // Reset the image source
  170. };
  171.  
  172. // Detect images
  173. const detectarImagenes = () => {
  174. const elements = document.querySelectorAll('img, [style*="background-image"]');
  175. elements.forEach((target) => {
  176. if (target.tagName === 'IMG') {
  177. target.addEventListener('mouseenter', ampliarImagen);
  178. target.addEventListener('mouseleave', ocultarVentanaFlotante);
  179. } else if (target.style.backgroundImage) {
  180. target.addEventListener('mouseenter', ampliarImagen);
  181. target.addEventListener('mouseleave', ocultarVentanaFlotante);
  182. }
  183. });
  184. };
  185.  
  186. // Call the function to detect images
  187. detectarImagenes();
  188.  
  189. // Add a mutation observer to detect dynamically added images or background elements
  190. const observer = new MutationObserver(detectarImagenes);
  191. observer.observe(document.body, { childList: true, subtree: true });
  192. })();