hookehuyr

fix(PdfViewer): 改进缩放功能以保持视图中心位置

重构缩放逻辑,使用比例计算代替直接缩放比率,确保缩放时视图中心位置保持不变
移除平滑滚动以避免偏移抖动,直接设置滚动位置
......@@ -354,28 +354,40 @@ const handleClose = () => {
*/
const zoomIn = () => {
if (zoomLevel.value < 3) { // 最大放大到300%
// 记录缩放前的滚动位置
const pdfContainer = document.querySelector('.pdf-viewer-container .pdf-content');
if (pdfContainer) {
const centerX = pdfContainer.scrollLeft + pdfContainer.clientWidth / 2;
const centerY = pdfContainer.scrollTop + pdfContainer.clientHeight / 2;
const oldW = pdfContainer.scrollWidth;
const oldH = pdfContainer.scrollHeight;
const viewportW = pdfContainer.clientWidth;
const viewportH = pdfContainer.clientHeight;
const centerX = pdfContainer.scrollLeft + viewportW / 2;
const centerY = pdfContainer.scrollTop + viewportH / 2;
const anchorRatioX = oldW > 0 ? centerX / oldW : 0;
const anchorRatioY = oldH > 0 ? centerY / oldH : 0;
const oldZoom = zoomLevel.value;
zoomLevel.value = Math.min(3, zoomLevel.value + 0.25);
const newZoom = zoomLevel.value;
// 使用nextTick确保DOM更新后再调整滚动位置
nextTick(() => {
const zoomRatio = newZoom / oldZoom;
const newScrollLeft = centerX * zoomRatio - pdfContainer.clientWidth / 2;
const newScrollTop = centerY * zoomRatio - pdfContainer.clientHeight / 2;
pdfContainer.scrollTo({
left: Math.max(0, newScrollLeft),
top: Math.max(0, newScrollTop),
behavior: 'smooth'
});
const newW = pdfContainer.scrollWidth;
const newH = pdfContainer.scrollHeight;
let targetCenterX = newW * anchorRatioX;
let targetCenterY = newH * anchorRatioY;
let newScrollLeft = Math.max(0, targetCenterX - viewportW / 2);
let newScrollTop = Math.max(0, targetCenterY - viewportH / 2);
newScrollLeft = Math.min(newScrollLeft, Math.max(0, newW - viewportW));
newScrollTop = Math.min(newScrollTop, Math.max(0, newH - viewportH));
// 直接赋值避免平滑滚动导致的偏移抖动
pdfContainer.scrollLeft = newScrollLeft;
pdfContainer.scrollTop = newScrollTop;
});
} else {
zoomLevel.value = Math.min(3, zoomLevel.value + 0.25);
}
}
};
......@@ -385,28 +397,39 @@ const zoomIn = () => {
*/
const zoomOut = () => {
if (zoomLevel.value > 0.5) { // 最小缩小到50%
// 记录缩放前的滚动位置
const pdfContainer = document.querySelector('.pdf-viewer-container .pdf-content');
if (pdfContainer) {
const centerX = pdfContainer.scrollLeft + pdfContainer.clientWidth / 2;
const centerY = pdfContainer.scrollTop + pdfContainer.clientHeight / 2;
const oldW = pdfContainer.scrollWidth;
const oldH = pdfContainer.scrollHeight;
const viewportW = pdfContainer.clientWidth;
const viewportH = pdfContainer.clientHeight;
const centerX = pdfContainer.scrollLeft + viewportW / 2;
const centerY = pdfContainer.scrollTop + viewportH / 2;
const anchorRatioX = oldW > 0 ? centerX / oldW : 0;
const anchorRatioY = oldH > 0 ? centerY / oldH : 0;
const oldZoom = zoomLevel.value;
zoomLevel.value = Math.max(0.5, zoomLevel.value - 0.25);
const newZoom = zoomLevel.value;
// 使用nextTick确保DOM更新后再调整滚动位置
nextTick(() => {
const zoomRatio = newZoom / oldZoom;
const newScrollLeft = centerX * zoomRatio - pdfContainer.clientWidth / 2;
const newScrollTop = centerY * zoomRatio - pdfContainer.clientHeight / 2;
pdfContainer.scrollTo({
left: Math.max(0, newScrollLeft),
top: Math.max(0, newScrollTop),
behavior: 'smooth'
});
const newW = pdfContainer.scrollWidth;
const newH = pdfContainer.scrollHeight;
let targetCenterX = newW * anchorRatioX;
let targetCenterY = newH * anchorRatioY;
let newScrollLeft = Math.max(0, targetCenterX - viewportW / 2);
let newScrollTop = Math.max(0, targetCenterY - viewportH / 2);
newScrollLeft = Math.min(newScrollLeft, Math.max(0, newW - viewportW));
newScrollTop = Math.min(newScrollTop, Math.max(0, newH - viewportH));
pdfContainer.scrollLeft = newScrollLeft;
pdfContainer.scrollTop = newScrollTop;
});
} else {
zoomLevel.value = Math.max(0.5, zoomLevel.value - 0.25);
}
}
};
......@@ -417,15 +440,10 @@ const zoomOut = () => {
const resetZoom = () => {
const pdfContainer = document.querySelector('.pdf-viewer-container .pdf-content');
if (pdfContainer) {
// 重置到顶部中央位置
zoomLevel.value = 1;
nextTick(() => {
pdfContainer.scrollTo({
left: 0,
top: 0,
behavior: 'smooth'
});
pdfContainer.scrollLeft = 0;
pdfContainer.scrollTop = 0;
});
} else {
zoomLevel.value = 1;
......