stable-diffusion-webui-zoom.../javascript/zoomimage.js

250 lines
8.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

onUiLoaded(function () {
let imageContainer = document.getElementById("lightboxModal");
imageContainer.style.width = "100%";
imageContainer.style.height = "100%";
imageContainer.style.overflow = "hidden";
function disableClose(e) {
e.stopPropagation();
}
let modalControls = imageContainer.getElementsByClassName("modalControls")[0];
if (modalControls) {
modalControls.style.position = "relative";
modalControls.style.zIndex = 1;
}
let img = imageContainer.querySelector("img");
img.style.width = "auto";
img.style.maxWidth = "100%";
img.style.height = "auto";
img.style.maxHeight = "100%";
let scale = 1;
let lastX = 0;
let lastY = 0;
let lastLen = 1;
let offsetX = 0;
let offsetY = 0;
let isDragging = false;
let touchStore = {};
let moveFunTimer = setTimeout(() => {}, 0);
let moveFunLastExecTime = Date.now();
let event = {
wheel: function (event) {
event.stopPropagation();
event.preventDefault();
img.style.transition = "transform 0.3s ease";
let delta = Math.max(-1, Math.min(1, event.wheelDelta || -event.detail));
let zoomStep = 0.1;
let zoom = 1 + delta * zoomStep;
let lastScale = scale;
scale *= zoom;
scale = Math.max(0.1, scale);
// 图片中心坐标
let centerX = imageContainer.offsetWidth / 2;
let centerY = imageContainer.offsetHeight / 2;
// 图片中心坐标
let imgCenterX = offsetX + centerX;
let imgCenterY = offsetY + centerY;
// 缩放后坐标偏移 = 缩放后图片中心坐标 - 页面中心坐标
// 缩放后图片中心坐标 = 缩放中心坐标 - 缩放后距离
// 缩放后距离 = (缩放前距离 / 之前的缩放比) *之后的缩放比
// 缩放前距离 = 缩放中心坐标 - 之前的图片中心坐标
// 之前的图片中心坐标 = 页面中心坐标 + 坐标偏移
offsetX =
event.clientX -
((event.clientX - imgCenterX) / lastScale) * scale -
centerX;
offsetY =
event.clientY -
((event.clientY - imgCenterY) / lastScale) * scale -
centerY;
img.style.transform =
"translate(" + offsetX + "px, " + offsetY + "px) scale(" + scale + ")";
},
mousedown: function (event) {
event.stopPropagation();
isDragging = true;
lastX = event.clientX - offsetX;
lastY = event.clientY - offsetY;
img.style.cursor = "grabbing";
},
mousemove: function (event) {
if (isDragging) {
img.style.transition = "";
event.stopPropagation();
event.preventDefault();
img.onclick = disableClose;
let deltaX = event.clientX - lastX;
let deltaY = event.clientY - lastY;
offsetX = deltaX;
offsetY = deltaY;
img.style.transform =
"translate(" + deltaX + "px, " + deltaY + "px) scale(" + scale + ")";
}
},
mouseup: function (event) {
event.stopPropagation();
isDragging = false;
img.style.cursor = "grab";
},
mouseleave: function (event) {
event.stopPropagation();
isDragging = false;
img.style.cursor = "grab";
},
reset() {
scale = 1;
lastX = 0;
lastY = 0;
last2X = 0;
last2Y = 0;
offsetX = 0;
offsetY = 0;
touchStore = {};
img.style.transform = "none";
img.onclick = undefined;
},
touchcancel: function (event) {
event.stopPropagation();
event.preventDefault();
img.onclick = undefined;
img.style.transition = "";
// 获取手势缩放比例
let newScale = scale * event.scale;
// 设置img标签的样式实现缩放效果
img.style.transform =
"translate(" + offsetX + "px, " + offsetY + "px) scale(" + scale + ")";
},
touchend: function (event) {
// 更新缩放比例
event.stopPropagation();
img.onclick = undefined;
if (!event.targetTouches.length) {
touchStore.tpuchScale = false;
}
},
touchstart: function (event) {
event.stopPropagation();
if (!touchStore.tpuchScale) {
lastX = event.targetTouches[0].clientX - offsetX;
lastY = event.targetTouches[0].clientY - offsetY;
}
if (event.targetTouches[1]) {
touchStore.tpuchScale = true;
touchStore.last1X = event.targetTouches[0].clientX;
touchStore.last1Y = event.targetTouches[0].clientY;
touchStore.last2X = event.targetTouches[1].clientX;
touchStore.last2Y = event.targetTouches[1].clientY;
touchStore.scale = scale;
lastLen = Math.sqrt(
Math.pow(touchStore.last2X - touchStore.last1X, 2) +
Math.pow(touchStore.last2Y - touchStore.last1Y, 2)
);
}
},
touchmove: function (event) {
event.stopPropagation();
event.preventDefault();
img.onclick = disableClose;
if (event.targetTouches[1]) {
touchStore.delta1X = event.targetTouches[0].clientX;
touchStore.delta1Y = event.targetTouches[0].clientY;
touchStore.delta2X = event.targetTouches[1].clientX;
touchStore.delta2Y = event.targetTouches[1].clientY;
let centerX = imageContainer.offsetWidth / 2;
let centerY = imageContainer.offsetHeight / 2;
let deltaLen = Math.sqrt(
Math.pow(touchStore.delta2X - touchStore.delta1X, 2) +
Math.pow(touchStore.delta2Y - touchStore.delta1Y, 2)
);
let zoom = deltaLen / lastLen;
let lastScale = scale;
scale = touchStore.scale * zoom;
scale = Math.max(0.1, scale);
// 当前缩放中心坐标
let deltaCenterX =
touchStore.delta1X + (touchStore.delta2X - touchStore.delta1X) / 2;
let deltaCenterY =
touchStore.delta1Y + (touchStore.delta2Y - touchStore.delta1Y) / 2;
// 图片中心坐标
let imgCenterX = offsetX + centerX;
let imgCenterY = offsetY + centerY;
// 计算缩放后的图片中心偏移
offsetX =
deltaCenterX -
((deltaCenterX - imgCenterX) / lastScale) * scale -
centerX;
offsetY =
deltaCenterY -
((deltaCenterY - imgCenterY) / lastScale) * scale -
centerY;
function moveFun() {
if (Date.now() - moveFunLastExecTime < 5) return;
img.style.transition = "transform 0.3s ease";
img.style.transform =
"translate(" +
offsetX +
"px, " +
offsetY +
"px) scale(" +
scale +
")";
}
if (Date.now() - moveFunLastExecTime >= 50) {
moveFun();
moveFunLastExecTime = Date.now();
} else {
clearTimeout(moveFunTimer);
moveFunTimer = setTimeout(() => {
moveFun();
}, 50);
}
} else if (!touchStore.tpuchScale) {
img.style.transition = "";
offsetX = event.targetTouches[0].clientX - lastX;
offsetY = event.targetTouches[0].clientY - lastY;
img.style.transform =
"translate(" +
offsetX +
"px, " +
offsetY +
"px) scale(" +
scale +
")";
}
},
};
function reloadZoomEvent(new_event) {
if (!new_event) return;
imageContainer.removeEventListener("click", event.reset);
imageContainer.removeEventListener("wheel", event.wheel);
img.removeEventListener("mousedown", event.mousedown);
img.removeEventListener("mousemove", event.mousemove);
img.removeEventListener("mouseup", event.mouseup);
img.removeEventListener("mouseleave", event.mouseleave);
// 移动端
imageContainer.removeEventListener("touchend", event.touchend);
imageContainer.removeEventListener("touchstart", event.touchstart);
imageContainer.removeEventListener("touchmove", event.touchmove);
event = new_event;
imageContainer.addEventListener("click", event.reset);
imageContainer.addEventListener("wheel", event.wheel);
img.addEventListener("mousedown", event.mousedown);
img.addEventListener("mousemove", event.mousemove);
img.addEventListener("mouseup", event.mouseup);
img.addEventListener("mouseleave", event.mouseleave);
img.ondrag =
img.ondragend =
img.ondragstart =
function (e) {
e.stopPropagation();
e.preventDefault();
};
// 移动端
imageContainer.addEventListener("touchend", event.touchend);
imageContainer.addEventListener("touchstart", event.touchstart);
imageContainer.addEventListener("touchmove", event.touchmove);
}
reloadZoomEvent(event);
});