Hi folks,
I want to zoom in on an image. Asked and found out that zooming is not supported on an image, but that it may be possible using a coded component.
Anybody who has implemented such a component and if so any tips or code I can borrow/steal :)?
Hi!
I have no experience with implementing such a component, but I’m guessing it’s possible using Javascript.
We have a feature request registered for supporting zooming on an image in the platform, but there is currently no planned ETA for this feature. Will register that it has been requested again, however!
1 Like
Hi @Lynfot I’ve used a coded component and Hammer.js for this. It’s working nicely on desktop and mobile in my projects.
Script:
let _scr = zoom.data.source.get()
const imageUrl = _scr;
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;
}
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;
}
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;
});
Hope this helps.
4 Likes
Hello! Release 114 includes better support for fullscreen preview with zoom on images. This feature is behind a feature flag as it has not yet been tested on a large scale. If you want this feature enabled in your solution, please send me a dm or an e-mail.