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.3
// @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';

    // Configuration options (you can adjust these values)
    const MAX_WIDTH = 450;  // Maximum width of the enlarged image
    const MAX_HEIGHT = 500; // Maximum height of the enlarged image
    const ZOOM_FACTOR = 2;  // Zoom factor (1x, 1.5x, 2x, 3x, etc)

    // Styles
    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;
            padding: 0px;
            pointer-events: none;
            height: auto;
            width: auto;
            box-sizing: border-box;
        }
        .ampliar-img-flotante img {
            width: 100%;
            height: 100%;
            object-fit: contain;
            display: block;
            margin: 0;
            box-sizing: border-box;
        }
    `);

    // Create the floating window
    const ventanaFlotante = document.createElement('div');
    ventanaFlotante.classList.add('ampliar-img-flotante');
    const imagenFlotante = document.createElement('img');
    ventanaFlotante.appendChild(imagenFlotante);
    document.body.appendChild(ventanaFlotante);

    // Function to enlarge the image with the zoom factor
    const ampliarImagen = (event) => {
        const target = event.target;

        let imgSrc = '';

        if (target.tagName === 'IMG') {
            // If the element is an <img>, use the src attribute
            imgSrc = target.src;
        } else if (target.style.backgroundImage) {
            // If the element has a background image, extract the URL
            imgSrc = target.style.backgroundImage.replace(/^url\(["']?/, '').replace(/["']?\)$/, '');
        }

        // Skip if the image source is not found or is an unwanted source
        if (!imgSrc || imgSrc.includes('youtube.com') || imgSrc.includes('gstatic.com')) {
            return;
        }


        const img = new Image();
        img.onload = () => {
            const widthWithZoom = img.width * ZOOM_FACTOR;
            const heightWithZoom = img.height * ZOOM_FACTOR;

            let finalWidth, finalHeight;

            if (img.width > img.height) {
                finalWidth = Math.min(widthWithZoom, MAX_WIDTH);
                finalHeight = (img.height * finalWidth) / img.width;
                if (finalHeight > MAX_HEIGHT) {
                    finalHeight = MAX_HEIGHT;
                    finalWidth = (img.width * finalHeight) / img.height;
                }
            } else {
                finalHeight = Math.min(heightWithZoom, MAX_HEIGHT);
                finalWidth = (img.width * finalHeight) / img.height;
                if (finalWidth > MAX_WIDTH) {
                    finalWidth = MAX_WIDTH;
                    finalHeight = (img.height * finalWidth) / img.width;
                }
            }

            imagenFlotante.src = imgSrc;
            ventanaFlotante.style.display = 'block';
            ventanaFlotante.style.width = `${finalWidth}px`;
            ventanaFlotante.style.height = `${finalHeight}px`;

            // Calculate the position of the floating window
            const { top, left, width, height } = target.getBoundingClientRect();
            let newTop = top + window.scrollY;
            let newLeft = left + width + window.scrollX;

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

            // Adjust the position so it doesn't overflow to the right
            if (newLeft + ventanaFlotante.offsetWidth > viewportWidth) {
                newLeft = left - ventanaFlotante.offsetWidth + window.scrollX;
            }

            // Adjust the position so it doesn't overflow to the bottom
            if (newTop + ventanaFlotante.offsetHeight > viewportHeight + window.scrollY) {
                newTop = top + height + window.scrollY - ventanaFlotante.offsetHeight;
            }

            // Adjust the position so it doesn't overflow to the top
            if (newTop < window.scrollY) {
                newTop = window.scrollY;
            }

            // Adjust the position so it doesn't overflow to the bottom
            if (newTop + ventanaFlotante.offsetHeight > viewportHeight + window.scrollY) {
                newTop = viewportHeight + window.scrollY - ventanaFlotante.offsetHeight;
            }

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

    // Hide the floating window
    const ocultarVentanaFlotante = () => {
        ventanaFlotante.style.display = 'none';
    };

    // Detect images
    const detectarImagenes = () => {
        const elements = document.querySelectorAll('img, [style*="background-image"]');
        elements.forEach((target) => {
            if (target.tagName === 'IMG') {
                target.addEventListener('mouseenter', ampliarImagen);
                target.addEventListener('mouseleave', ocultarVentanaFlotante);
            } else if (target.style.backgroundImage) {
                target.addEventListener('mouseenter', ampliarImagen);
                target.addEventListener('mouseleave', ocultarVentanaFlotante);
            }
        });
    };

    // Call the function to detect images
    detectarImagenes();

    // Add a mutation observer to detect dynamically added images or background elements
    const observer = new MutationObserver(detectarImagenes);
    observer.observe(document.body, { childList: true, subtree: true });
})();