ben.wiegand.pw/www/image-modal.js
2024-09-08 14:54:38 -07:00

101 lines
3.1 KiB
JavaScript

const images = document.getElementsByClassName('project-image');
for (const image of images) {
const modal = image.querySelector('.modal')
const lazy_image = image.querySelector('.lazy-image')
const zoom = modal.querySelector('input')
const open = image.querySelector('input');
const thumbnail = image.querySelector('img');
// for pan
let grabbed = false;
let startX = 0;
let startY = 0;
// for zoom
let clickX = 0;
let clickY = 0;
let initW = lazy_image.clientWidth;
let initH = lazy_image.clientHeight;
// for aspect
function fixAspectRatio() {
let img_aspect = thumbnail.clientWidth / thumbnail.clientHeight
let window_aspect = window.innerWidth / window.innerHeight;
let base = zoom.checked ? 200 : 90;
if (img_aspect > window_aspect) {
// img wider than window
lazy_image.style['min-width'] = base + 'vw';
lazy_image.style['min-height'] = (base * thumbnail.clientHeight / thumbnail.clientWidth) + 'vw';
} else {
// window wider than img
lazy_image.style['min-width'] = (base * img_aspect) + 'vh';
lazy_image.style['min-height'] = base + 'vh';
}
}
thumbnail.addEventListener('load', fixAspectRatio);
// pan the image
lazy_image.addEventListener('mouseleave', () => {grabbed = false;});
lazy_image.addEventListener('mouseup', () => {
grabbed = false;
});
lazy_image.addEventListener('mousedown', e => {
grabbed = true;
startX = modal.scrollLeft + e.pageX;
startY = modal.scrollTop + e.pageY;
// set stuff for zoom
clickX = e.clientX - lazy_image.offsetLeft;
clickY = e.clientY - lazy_image.offsetTop;
initW = lazy_image.clientWidth;
initH = lazy_image.clientHeight;
});
lazy_image.addEventListener('mousemove', e => {
if(!grabbed) return;
modal.scrollLeft = startX - e.pageX;
modal.scrollTop = startY - e.pageY;
});
// unzoom on close
open.addEventListener('change', () => {
if (!open.checked) zoom.checked = false;
});
// zoom to click target
zoom.addEventListener('change', e => {
fixAspectRatio();
if (zoom.checked) {
zoom_factor = Math.max(
lazy_image.clientWidth / initW,
lazy_image.clientHeight / initH
);
x = clickX * zoom_factor - (window.innerWidth / 2);
y = clickY * zoom_factor - (window.innerHeight / 2);
modal.scrollLeft = x;
modal.scrollTop = y;
}
});
// resize image plane to match image aspect ratio
open.addEventListener('change', e => {
if (open.checked) {
fixAspectRatio();
window.addEventListener('resize', fixAspectRatio);
} else {
window.removeEventListener('resize', fixAspectRatio);
}
});
// close image on escape key
document.addEventListener('keydown', e => {
if (e.key == 'Escape') {
open.checked = false;
zoom.checked = false;
}
});
}