Scaling Images!

Hello fluffy animals on the internet! I added ability to zoom into images on this website! Now you can see every detail in my artworks :3.

How it works:

  1. Click on any image
  2. Zoom-in or Zoom-out with scroll-wheel

Script:



document.addEventListener('DOMContentLoaded', function() {
    // Create the fullscreen viewer elements
    const viewer = document.createElement('div');
    viewer.id = 'wp-image-viewer';
    viewer.style.cssText = `
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(0,0,0,0.9);
        display: flex;
        justify-content: center;
        align-items: center;
        z-index: 999999;
        opacity: 0;
        transition: opacity 0.3s ease;
        pointer-events: none;
        cursor: zoom-out;
    `;

    const image = document.createElement('img');
    image.style.maxHeight = 'calc(100% - 20px)';
    image.style.maxWidth = 'calc(100% - 20px)';
    image.style.objectFit = 'contain';
    image.style.transform = 'scale(1)';
    image.style.cursor = 'zoom-in';

    const closeBtn = document.createElement('button');
    closeBtn.innerHTML = '×';
    closeBtn.style.cssText = `
        position: absolute;
        top: 20px;
        right: 20px;
        background: none;
        border: none;
        color: white;
        font-size: 40px;
        cursor: pointer;
        z-index: 10;
    `;

    // Zoom controls
    const zoomControls = document.createElement('div');
    zoomControls.style.cssText = `
        position: absolute;
        bottom: 20px;
        left: 50%;
        transform: translateX(-50%);
        display: flex;
        gap: 10px;
        z-index: 10;
    `;

    const zoomInBtn = document.createElement('button');
    zoomInBtn.innerHTML = '+';
    zoomInBtn.style.cssText = `
        background: rgba(255,255,255,0.2);
        border: none;
        color: white;
        font-size: 24px;
        width: 40px;
        height: 40px;
        border-radius: 50%;
        cursor: pointer;
        display: flex;
        justify-content: center;
        align-items: center;
    `;

    const zoomOutBtn = document.createElement('button');
    zoomOutBtn.innerHTML = '−';
    zoomOutBtn.style.cssText = zoomInBtn.style.cssText;

    const resetZoomBtn = document.createElement('button');
    resetZoomBtn.innerHTML = '↺';
    resetZoomBtn.style.cssText = zoomInBtn.style.cssText;

    zoomControls.appendChild(zoomInBtn);
    zoomControls.appendChild(zoomOutBtn);
    zoomControls.appendChild(resetZoomBtn);

    viewer.appendChild(image);
    viewer.appendChild(closeBtn);
    viewer.appendChild(zoomControls);
    document.body.appendChild(viewer);

    // Zoom state
    let currentScale = 1;
    const minScale = 0.5;
    const maxScale = 5;
    const zoomStep = 0.2;
    let isDragging = false;
    let startX = 0;
    let startY = 0;
    let scrollLeft = 0;
    let scrollTop = 0;

    // Find all eligible WordPress image containers
    const containers = document.querySelectorAll('.wp-block-image, .wp-block-media-text__media');
    
    containers.forEach(container => {
        // Recursively find the first image within the container
        const img = findFirstImage(container);
        if (!img) return;
        
        // Add click handler to the container
        container.style.cursor = 'zoom-in';
        container.addEventListener('click', function(e) {
            // Prevent triggering if clicked on nested links
            if (e.target.tagName === 'A') return;
            
            // Set image source and show viewer
            image.src = img.currentSrc || img.src;
            image.alt = img.alt || '';
            showViewer();
        });
    });

    // Viewer control functions
    function showViewer() {
        currentScale = 1;
        image.style.transform = 'scale(1)';
        viewer.style.opacity = 1;
        viewer.style.pointerEvents = 'all';
        document.body.style.overflow = 'hidden';
    }

    function hideViewer() {
        viewer.style.opacity = 0;
        viewer.style.pointerEvents = 'none';
        document.body.style.overflow = '';
    }

    // Zoom functions
    function zoomImage(scale) {
        currentScale = Math.min(maxScale, Math.max(minScale, scale));
        image.style.transform = `scale(${currentScale})`;
    }

    function zoomIn() {
        zoomImage(currentScale + zoomStep);
    }

    function zoomOut() {
        zoomImage(currentScale - zoomStep);
    }

    function resetZoom() {
        zoomImage(1);
    }

    // Panning functionality
    image.addEventListener('mousedown', (e) => {
        if (currentScale <= 1) return;
        
        isDragging = true;
        startX = e.pageX - image.offsetLeft;
        startY = e.pageY - image.offsetTop;
        scrollLeft = image.scrollLeft;
        scrollTop = image.scrollTop;
        image.style.cursor = 'grabbing';
    });

    document.addEventListener('mousemove', (e) => {
        if (!isDragging) return;
        
        e.preventDefault();
        const x = e.pageX - image.offsetLeft;
        const y = e.pageY - image.offsetTop;
        const walkX = (x - startX) * 2;
        const walkY = (y - startY) * 2;
        
        image.scrollLeft = scrollLeft - walkX;
        image.scrollTop = scrollTop - walkY;
    });

    document.addEventListener('mouseup', () => {
        isDragging = false;
        image.style.cursor = currentScale > 1 ? 'grab' : 'zoom-in';
    });

    // Event listeners for viewer
    viewer.addEventListener('click', (e) => {
        if (e.target === viewer) hideViewer();
    });
    
    closeBtn.addEventListener('click', hideViewer);
    
    image.addEventListener('click', (e) => {
        if (currentScale > 1) {
            // If zoomed, clicking zooms out
            resetZoom();
        } else {
            // If not zoomed, clicking toggles zoom
            zoomIn();
        }
    });

    // Mouse wheel zoom
    image.addEventListener('wheel', (e) => {
        e.preventDefault();
        if (e.deltaY < 0) {
            // Zoom in when scrolling up
            zoomIn();
        } else {
            // Zoom out when scrolling down
            zoomOut();
        }
    });

    // Button events
    zoomInBtn.addEventListener('click', zoomIn);
    zoomOutBtn.addEventListener('click', zoomOut);
    resetZoomBtn.addEventListener('click', resetZoom);

    // Close with ESC key
    document.addEventListener('keydown', e => {
        if (e.key === 'Escape' && viewer.style.opacity === '1') hideViewer();
    });

    // Recursive function to find first image
    function findFirstImage(element) {
        if (element.tagName === 'IMG') return element;
        const children = element.children;
        for (let i = 0; i < children.length; i++) {
            const found = findFirstImage(children[i]);
            if (found) return found;
        }
        return null;
    }
});

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *