hookehuyr

feat(PdfViewer): 添加双指缩放手势支持

实现PDF查看器的双指缩放功能,包括触摸开始、移动和结束的完整手势处理
......@@ -536,18 +536,117 @@ const addPreventSaveListeners = () => {
return false;
});
// 防止触摸回调(移动端长按)
pdfContainer.addEventListener('touchstart', (e) => {
if (e.touches.length > 1) {
e.preventDefault();
}
});
// 添加双指缩放手势支持
addPinchZoomListeners(pdfContainer);
}
};
// 防止双指缩放等手势
pdfContainer.addEventListener('gesturestart', (e) => {
// 双指缩放相关变量
let initialDistance = 0;
let initialZoom = 1;
let isZooming = false;
/**
* 添加双指缩放手势监听器
*/
const addPinchZoomListeners = (container) => {
let touches = [];
// 计算两点间距离
const getDistance = (touch1, touch2) => {
const dx = touch1.clientX - touch2.clientX;
const dy = touch1.clientY - touch2.clientY;
return Math.sqrt(dx * dx + dy * dy);
};
// 获取两点中心位置
const getCenter = (touch1, touch2) => {
return {
x: (touch1.clientX + touch2.clientX) / 2,
y: (touch1.clientY + touch2.clientY) / 2
};
};
// 触摸开始
container.addEventListener('touchstart', (e) => {
touches = Array.from(e.touches);
if (touches.length === 2) {
// 双指触摸开始
e.preventDefault();
});
}
isZooming = true;
initialDistance = getDistance(touches[0], touches[1]);
initialZoom = zoomLevel.value;
} else if (touches.length > 2) {
// 超过两指时阻止默认行为
e.preventDefault();
}
}, { passive: false });
// 触摸移动
container.addEventListener('touchmove', (e) => {
if (e.touches.length === 2 && isZooming) {
e.preventDefault();
const currentTouches = Array.from(e.touches);
const currentDistance = getDistance(currentTouches[0], currentTouches[1]);
const scale = currentDistance / initialDistance;
// 计算新的缩放级别
let newZoom = initialZoom * scale;
newZoom = Math.max(0.5, Math.min(3, newZoom)); // 限制缩放范围
// 获取缩放中心点
const center = getCenter(currentTouches[0], currentTouches[1]);
const rect = container.getBoundingClientRect();
const centerX = center.x - rect.left;
const centerY = center.y - rect.top;
// 应用缩放
applyPinchZoom(newZoom, centerX, centerY, container);
}
}, { passive: false });
// 触摸结束
container.addEventListener('touchend', (e) => {
if (isZooming && e.touches.length < 2) {
isZooming = false;
initialDistance = 0;
initialZoom = zoomLevel.value;
}
});
// 触摸取消
container.addEventListener('touchcancel', (e) => {
isZooming = false;
initialDistance = 0;
initialZoom = zoomLevel.value;
});
};
/**
* 应用双指缩放
*/
const applyPinchZoom = (newZoom, centerX, centerY, container) => {
const oldZoom = zoomLevel.value;
const oldScrollLeft = container.scrollLeft;
const oldScrollTop = container.scrollTop;
// 更新缩放级别
zoomLevel.value = newZoom;
// 等待DOM更新后调整滚动位置
nextTick(() => {
const zoomRatio = newZoom / oldZoom;
// 计算新的滚动位置,以缩放中心为锚点
const newScrollLeft = (oldScrollLeft + centerX) * zoomRatio - centerX;
const newScrollTop = (oldScrollTop + centerY) * zoomRatio - centerY;
// 应用新的滚动位置
container.scrollLeft = Math.max(0, newScrollLeft);
container.scrollTop = Math.max(0, newScrollTop);
});
};
</script>
......