Zoom on Hover

Zoom on Hover enlarges images when you hover over them.

目前為 2024-11-25 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Zoom on Hover
// @name:es      Zoom on Hover
// @version      1.0
// @description  Zoom on Hover enlarges images when you hover over them.
// @description:es Zoom on Hover amplía las imágenes cuando pasas el cursor sobre ellas
// @author       Adam Jensen
// @match        *://*/*
// @grant        GM_addStyle
// @license      MIT
// @namespace https://greasyfork.org/users/1398884
// ==/UserScript==

(function() {
    'use strict';

    // Estilos
    GM_addStyle(`
        .ampliar-img-flotante {
            position: absolute;
            z-index: 9999;
            border: 2px solid #ccc;
            background: rgba(255, 255, 255, 0.9);
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
            display: none;
            overflow: hidden;
            padding: 5px;
            pointer-events: none;
            /* Eliminada la transición para evitar el "parpadeo" */
        }
        .ampliar-img-flotante img {
            width: 100%;
            height: 100%;
            object-fit: contain; /* Mantener la relación de aspecto sin recorte */
        }
    `);

    // Crear la ventana flotante
    const ventanaFlotante = document.createElement('div');
    ventanaFlotante.classList.add('ampliar-img-flotante');
    const imagenFlotante = document.createElement('img');
    ventanaFlotante.appendChild(imagenFlotante);
    document.body.appendChild(ventanaFlotante);

    // Función para ampliar la imagen
    const ampliarImagen = (event) => {
        const img = event.target;

        if (img.tagName !== 'IMG' || img.width < 50 || img.height < 50 || img.src.includes('youtube.com') || img.src.includes('gstatic.com')) {
            return; // No ampliar si es un logo de YouTube o una imagen pequeña
        }

        // Crear una nueva imagen para cargarla
        const imagenPrevia = new Image();
        imagenPrevia.src = img.src;

        // Esperamos a que la imagen se cargue
        imagenPrevia.onload = () => {
            // Ajustar el tamaño del contenedor flotante según las dimensiones de la imagen
            const imageAspectRatio = imagenPrevia.width / imagenPrevia.height;
            const containerAspectRatio = ventanaFlotante.offsetWidth / ventanaFlotante.offsetHeight;

            if (imageAspectRatio > containerAspectRatio) {
                // Si la imagen es más ancha que el contenedor, ajustamos el ancho
                ventanaFlotante.style.width = `${Math.min(imagenPrevia.width, 600)}px`;
                ventanaFlotante.style.height = 'auto';
            } else {
                // Si la imagen es más alta que ancha, ajustamos la altura
                ventanaFlotante.style.height = `${Math.min(imagenPrevia.height, 600)}px`;
                ventanaFlotante.style.width = 'auto';
            }

            // Asignar la imagen al contenedor flotante y mostrarla
            imagenFlotante.src = img.src;
            ventanaFlotante.style.display = 'block';

            // Calcular la posición de la ventana flotante
            const { top, left, width, height } = img.getBoundingClientRect();
            let newTop = top + window.scrollY;
            let newLeft = left + width + 10 + window.scrollX;

            const viewportWidth = window.innerWidth;
            const viewportHeight = window.innerHeight;

            // Ajustar la posición para que no se salga por la derecha
            if (newLeft + ventanaFlotante.offsetWidth > viewportWidth) {
                newLeft = left - ventanaFlotante.offsetWidth - 10 + window.scrollX;
            }

            // Ajustar la posición para que no se salga por la parte inferior
            if (newTop + ventanaFlotante.offsetHeight > viewportHeight + window.scrollY) {
                newTop = top + height + window.scrollY - ventanaFlotante.offsetHeight - 10;
            }

            // Ajustar la posición para que no se salga por la parte superior
            if (newTop < window.scrollY) {
                newTop = window.scrollY + 10;
            }

            ventanaFlotante.style.top = `${newTop}px`;
            ventanaFlotante.style.left = `${newLeft}px`;
        };
    };

    // Ocultar ventana flotante
    const ocultarVentanaFlotante = () => {
        ventanaFlotante.style.display = 'none';
    };

    // Detectar imágenes en la página
    const detectarImagenes = () => {
        const images = document.querySelectorAll('img'); // Sólo imágenes <img> (no background-image)
        images.forEach((img) => {
            if (img.tagName === 'IMG') {
                img.addEventListener('mouseenter', ampliarImagen);
                img.addEventListener('mouseleave', ocultarVentanaFlotante);
            }
        });
    };

    // Llamar a la función para detectar imágenes
    detectarImagenes();

    // Añadir un observador de cambios en el DOM para detectar imágenes dinámicas
    const observer = new MutationObserver(detectarImagenes);
    observer.observe(document.body, { childList: true, subtree: true });
})();