'use strict'; const imageUrl = 'https://source.unsplash.com/random'; const imageContainer = document.querySelector('.imageContainer'); const hud = document.querySelector('#hud'); let minScale = 1; let maxScale = 4; let imageWidth; let imageHeight; let containerWidth; let containerHeight; let displayImageX = 0; let displayImageY = 0; let displayImageScale = 1; let displayDefaultWidth; let displayDefaultHeight; let rangeX = 0; let rangeMaxX = 0; let rangeMinX = 0; let rangeY = 0; let rangeMaxY = 0; let rangeMinY = 0; let displayImageRangeY = 0; let displayImageCurrentX = 0; let displayImageCurrentY = 0; let displayImageCurrentScale = 1; function resizeContainer() { containerWidth = imageContainer.offsetWidth; containerHeight = imageContainer.offsetHeight; if (displayDefaultWidth !== undefined && displayDefaultHeight !== undefined) { displayDefaultWidth = displayImage.offsetWidth; displayDefaultHeight = displayImage.offsetHeight; updateRange(); displayImageCurrentX = clamp( displayImageX, rangeMinX, rangeMaxX ); displayImageCurrentY = clamp( displayImageY, rangeMinY, rangeMaxY ); updateDisplayImage( displayImageCurrentX, displayImageCurrentY, displayImageCurrentScale ); } } resizeContainer(); function clamp(value, min, max) { return Math.min(Math.max(min, value), max); } function clampScale(newScale) { return clamp(newScale, minScale, maxScale); } window.addEventListener('resize', resizeContainer, true); const displayImage = new Image(); displayImage.src = imageUrl; displayImage.onload = function(){ imageWidth = displayImage.width; imageHeight = displayImage.height; imageContainer.appendChild(displayImage); displayImage.addEventListener('mousedown', e => e.preventDefault(), false); displayDefaultWidth = displayImage.offsetWidth; displayDefaultHeight = displayImage.offsetHeight; rangeX = Math.max(0, displayDefaultWidth - containerWidth); rangeY = Math.max(0, displayDefaultHeight - containerHeight); } imageContainer.addEventListener('wheel', e => { displayImageScale = displayImageCurrentScale = clampScale(displayImageScale + (e.wheelDelta / 800)); updateRange(); displayImageCurrentX = clamp(displayImageCurrentX, rangeMinX, rangeMaxX) displayImageCurrentY = clamp(displayImageCurrentY, rangeMinY, rangeMaxY) updateDisplayImage(displayImageCurrentX, displayImageCurrentY, displayImageScale); }, false); function updateDisplayImage(x, y, scale) { const transform = 'translateX(' + x + 'px) translateY(' + y + 'px) translateZ(0px) scale(' + scale + ',' + scale + ')'; displayImage.style.transform = transform; displayImage.style.WebkitTransform = transform; displayImage.style.msTransform = transform; updateHud(); } function updateRange() { rangeX = Math.max(0, Math.round(displayDefaultWidth * displayImageCurrentScale) - containerWidth); rangeY = Math.max(0, Math.round(displayDefaultHeight * displayImageCurrentScale) - containerHeight); rangeMaxX = Math.round(rangeX / 2); rangeMinX = 0 - rangeMaxX; rangeMaxY = Math.round(rangeY / 2); rangeMinY = 0 - rangeMaxY; } function updateHud() { let hudText = `
Current
Scale:     ${displayImageCurrentScale.toFixed(4)}
X:         ${displayImageCurrentX}
Y:         ${displayImageCurrentY}

Range
rangeX:    ${rangeX}
rangeMinX: ${rangeMinX}
rangeMaxX: ${rangeMaxX}

rangeY:    ${rangeY}
rangeMinY: ${rangeMinY}
rangeMaxY: ${rangeMaxY}

Updated
Scale:     ${displayImageScale.toFixed(4)}
X:         ${displayImageX}
Y:         ${displayImageY}
`; hud.innerHTML = hudText; } const hammertime = new Hammer(imageContainer); hammertime.get('pinch').set({ enable: true }); hammertime.get('pan').set({ direction: Hammer.DIRECTION_ALL }); hammertime.on('pan', ev => { displayImageCurrentX = clamp(displayImageX + ev.deltaX, rangeMinX, rangeMaxX); displayImageCurrentY = clamp(displayImageY + ev.deltaY, rangeMinY, rangeMaxY); updateDisplayImage(displayImageCurrentX, displayImageCurrentY, displayImageScale); }); hammertime.on('pinch pinchmove', ev => { displayImageCurrentScale = clampScale(ev.scale * displayImageScale); updateRange(); displayImageCurrentX = clamp(displayImageX + ev.deltaX, rangeMinX, rangeMaxX); displayImageCurrentY = clamp(displayImageY + ev.deltaY, rangeMinY, rangeMaxY); updateDisplayImage(displayImageCurrentX, displayImageCurrentY, displayImageCurrentScale); }); hammertime.on('panend pancancel pinchend pinchcancel', () => { displayImageScale = displayImageCurrentScale; displayImageX = displayImageCurrentX; displayImageY = displayImageCurrentY; });