Source: media/viewer/imagePreview.js

import 'photoswipe/style.css';
import 'photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css'

import { ImageTools } from "../utils/ImageTools.js";
import { VectorGraphics } from "../player/VectorGraphics.js"
import { showBlurredBackgroundImage } from './utils.js';

export { createLightboxImage }

/**
 * Display an image with lightbox support on a website.
 * @param {string} src - Image URL.
 * @param {number} width - Image width in pixel (ignores exif orientation, thus width > height for landscape).
 * @param {number} height - Image height in pixel (ignores exif orientation, thus width < height for portrait).
 * @param {string} [srcSet] - Image srcset attribute with width descriptor.
 * @return {Element} Image container.
 */
function createLightboxImage(src, width, height, srcset) {
    const [srcLightbox, srcsetLightbox] = ImageTools.improveLightboxPerformance(src, srcset);
    const container = document.createElement("div");
    container.innerHTML = `
            <a data-pswp-width="${width}"
                data-pswp-height="${height}"
                ${srcsetLightbox ? ('data-pswp-srcset="' + srcsetLightbox + '"') : ""}
                target="_blank"
                href="${srcLightbox}"
                class="preview-thumbnail-image">
                <div style="padding-bottom: min(calc(${height}/${width} * 100%), 100%);"></div>
                <img
                    data-sizes="auto"
                    data-src="${src}"
                    ${srcset ? ('data-srcset="' + srcset + '"') : ""}
                    onerror='this.removeAttribute("onerror"); this.src="${VectorGraphics.errorImage('Photo')}"; this.removeAttribute("srcset"); this.parentElement.style="pointer-events: none"'
                    class="lazyload"
                >
            </a>
        `;

    const mediaElement = container.querySelector('img');
    mediaElement.onload = (event) => {
        showBlurredBackgroundImage(event.target, container);
    }

    const options = {
        gallery: container,
        children: 'a',
        pswpModule: () => import("photoswipe"),
        wheelToZoom: true,
        bgOpacity: 0.98,
        initialZoomLevel: 'fit',
        secondaryZoomLevel: (zoomLevelObject) => {
            //Secondary zoom level is fill, but minimum 2 of fit
            return Math.max(2, zoomLevelObject.fill / zoomLevelObject.fit) * zoomLevelObject.fit
        },
        maxZoomLevel: 4.0,
        mainClass: "vef-ui viewer-lightbox"
    };

    import("lazysizes").then(lazysizes => {
        import("photoswipe/lightbox").then(PhotoswipeLightbox => {
            const lightbox = new PhotoswipeLightbox.default(options);
            lightbox.on('uiRegister', function () {
                lightbox.pswp.ui.registerElement({
                    name: 'zoom-level-indicator',
                    order: 8,
                    onInit: (el, pswp) => {
                        pswp.on('zoomPanUpdate', (e) => {
                            if (e.slide === pswp.currSlide) {
                                el.innerText = 'Zoom: ' + Math.round(pswp.currSlide.currZoomLevel * 100) + '%';
                            }
                        });
                    }
                })
            });

            lightbox.addFilter('contentErrorElement', (contentErrorElement, content) => {
                const imageElement = document.createElement('img');
                imageElement.src = VectorGraphics.errorImage('Photo');
                imageElement.style.height = "100%";
                imageElement.style.width = "100%";
                imageElement.style.top = "0px";
                imageElement.style.position = "absolute";
                return imageElement;
            });

            lightbox.init();
        })
    })

    return container;
}