У меня есть требование, при котором пользователь должен иметь возможность увеличивать и уменьшать масштаб с помощью событий pinch / pan / mouse-wheel.
Я пробовал это решение, и оно работает, за исключением того, что оно всегдаУвеличивает центр изображения независимо от того, где я пытаюсь увеличить.
Я просто хочу иметь возможность увеличивать, где бы я ни хотел увеличить.
Codepen:https://codepen.io/anon/pen/omjXbr
HTML
<div class="imageContainer"></div>
CSS
html, body {
background: #fff;
height: 100%;
margin: 0;
padding: 0;
}
.imageContainer {
width: 70%;
height: 96%;
max-width: 800px;
max-height: 600px;
position: absolute;
overflow: hidden;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
background: black;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.imageContainer > img {
display: block;
max-width:100%;
max-height:100%;
cursor: move;
touch-action: none;
}
Javascript
'use strict';
const imageUrl = 'https://source.unsplash.com/random';
const imageContainer = document.querySelector('.imageContainer');
const hud = document.querySelector('#hud');
let minScale = 1;
let maxScale = 6;
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;
});