import './lightbox.css' let images = [] /** @type {HTMLImageElement} */ let currentImage = null let currentIndexIndex = 0 let hideContainer function findOrCreateLightboxContainer () { const lightboxContainerSelector = '.lightbox-container' let lightBoxContainer = document.querySelector(lightboxContainerSelector) if (!lightBoxContainer) { lightBoxContainer = document.createElement('div') lightBoxContainer.className = 'lightbox-container' lightBoxContainer.innerHTML = ` ` addImageZoomListener(lightBoxContainer) hideContainer = () => { lightBoxContainer.classList.remove('show') document.body.classList.remove('no-scroll') currentImage = null } lightBoxContainer.querySelector('.lightbox-control-previous').addEventListener('click', (e) => { e.stopPropagation() switchImage(-1) }) lightBoxContainer.querySelector('.lightbox-control-next').addEventListener('click', (e) => { e.stopPropagation() switchImage(1) }) lightBoxContainer.querySelector('.lightbox-control-close').addEventListener('click', (e) => { e.stopPropagation() hideContainer() }) lightBoxContainer.addEventListener('click', (e) => { e.stopPropagation() hideContainer() }) document.body.appendChild(lightBoxContainer) } return lightBoxContainer } function switchImage (dir) { const lightBoxContainer = findOrCreateLightboxContainer() currentIndexIndex += dir if (currentIndexIndex >= images.length) { currentIndexIndex = 0 } else if (currentIndexIndex < 0) { currentIndexIndex = images.length - 1 } const img = images[currentIndexIndex] setImageInner(img, lightBoxContainer) } function setImageInner (img, lightBoxContainer) { const src = img.getAttribute('src') const alt = img.getAttribute('alt') lightBoxContainer.querySelector('.lightbox-inner').innerHTML = `${alt}` addImageDragListener(lightBoxContainer.querySelector('.lightbox-inner img')) } function onClickImage (img) { const lightBoxContainer = findOrCreateLightboxContainer() setImageInner(img, lightBoxContainer) lightBoxContainer.classList.add('show') document.body.classList.add('no-scroll') currentImage = img updateLightboxImages() } function updateLightboxImages () { images = [...document.querySelectorAll('.markdown-body img.md-image')] if (currentImage) { currentIndexIndex = images.findIndex(image => image === currentImage) } } function addImageZoomListener (container) { container.addEventListener('wheel', function (e) { // normalize scroll position as percentage e.preventDefault() /** @type {HTMLImageElement} */ const image = container.querySelector('img') if (!image) { return } let scale = image.getBoundingClientRect().width / image.offsetWidth scale += e.deltaY * -0.01 // Restrict scale scale = Math.min(Math.max(0.125, scale), 4) var transformValue = `scale(${scale})` image.style.WebkitTransform = transformValue image.style.MozTransform = transformValue image.style.OTransform = transformValue image.style.transform = transformValue }) } /** * @param {HTMLImageElement} image */ function addImageDragListener (image) { let moved = false let pos = [] const container = findOrCreateLightboxContainer() const inner = container.querySelector('.lightbox-inner') const onMouseDown = (evt) => { moved = true const { left, top } = image.getBoundingClientRect() pos = [ evt.pageX - left, evt.pageY - top ] } image.addEventListener('mousedown', onMouseDown) inner.addEventListener('mousedown', onMouseDown) const onMouseMove = (evt) => { if (!moved) { return } image.style.left = `${evt.pageX - pos[0]}px` image.style.top = `${evt.pageY - pos[1]}px` image.style.position = 'absolute' } image.addEventListener('mousemove', onMouseMove) inner.addEventListener('mousemove', onMouseMove) const onMouseUp = () => { moved = false pos = [] } image.addEventListener('mouseup', onMouseUp) inner.addEventListener('mouseup', onMouseUp) inner.addEventListener('click', (e) => { e.stopPropagation() }) image.addEventListener('click', (e) => { e.stopPropagation() }) } const init = () => { const markdownBody = document.querySelector('.markdown-body') if (!markdownBody) { return } markdownBody.addEventListener('click', function (e) { const img = e.target if (img.nodeName === 'IMG' && img.classList.contains('md-image')) { onClickImage(img) e.stopPropagation() } }) window.addEventListener('keydown', function (e) { if (!currentImage) { return } if (e.key === 'ArrowRight') { switchImage(1) e.stopPropagation() } else if (e.key === 'ArrowLeft') { switchImage(-1) e.stopPropagation() } else if (e.key === 'Escape') { if (hideContainer) { hideContainer() e.stopPropagation() } } }) } init()