feat(PdfViewer): 添加缩放时保持滚动位置功能
在PDF查看器中添加滚动位置记录功能,当用户进行缩放操作时,会基于当前视口中心点计算并保持相对滚动位置,提升用户体验
Showing
1 changed file
with
67 additions
and
1 deletions
| ... | @@ -110,6 +110,7 @@ const loadingProgress = ref(0); | ... | @@ -110,6 +110,7 @@ const loadingProgress = ref(0); |
| 110 | const loadingError = ref(false); | 110 | const loadingError = ref(false); |
| 111 | const errorMessage = ref(''); | 111 | const errorMessage = ref(''); |
| 112 | const zoomLevel = ref(1); // 缩放级别,1为100% | 112 | const zoomLevel = ref(1); // 缩放级别,1为100% |
| 113 | +const scrollPosition = ref({ x: 0, y: 0 }); // 记录滚动位置 | ||
| 113 | 114 | ||
| 114 | /** | 115 | /** |
| 115 | * 监听show属性变化,控制PDF加载 | 116 | * 监听show属性变化,控制PDF加载 |
| ... | @@ -171,7 +172,14 @@ const handleComplete = () => { | ... | @@ -171,7 +172,14 @@ const handleComplete = () => { |
| 171 | * @param {number} scrollOffset - 滚动偏移量 | 172 | * @param {number} scrollOffset - 滚动偏移量 |
| 172 | */ | 173 | */ |
| 173 | const handleScroll = (scrollOffset) => { | 174 | const handleScroll = (scrollOffset) => { |
| 174 | - // 可以在这里处理滚动事件 | 175 | + // 记录当前滚动位置 |
| 176 | + const pdfContainer = document.querySelector('.pdf-viewer-container .pdf-content'); | ||
| 177 | + if (pdfContainer) { | ||
| 178 | + scrollPosition.value = { | ||
| 179 | + x: pdfContainer.scrollLeft, | ||
| 180 | + y: pdfContainer.scrollTop | ||
| 181 | + }; | ||
| 182 | + } | ||
| 175 | }; | 183 | }; |
| 176 | 184 | ||
| 177 | /** | 185 | /** |
| ... | @@ -237,7 +245,29 @@ const retryLoad = () => { | ... | @@ -237,7 +245,29 @@ const retryLoad = () => { |
| 237 | */ | 245 | */ |
| 238 | const zoomIn = () => { | 246 | const zoomIn = () => { |
| 239 | if (zoomLevel.value < 3) { // 最大放大到300% | 247 | if (zoomLevel.value < 3) { // 最大放大到300% |
| 248 | + // 记录缩放前的滚动位置 | ||
| 249 | + const pdfContainer = document.querySelector('.pdf-viewer-container .pdf-content'); | ||
| 250 | + if (pdfContainer) { | ||
| 251 | + const centerX = pdfContainer.scrollLeft + pdfContainer.clientWidth / 2; | ||
| 252 | + const centerY = pdfContainer.scrollTop + pdfContainer.clientHeight / 2; | ||
| 253 | + | ||
| 254 | + const oldZoom = zoomLevel.value; | ||
| 240 | zoomLevel.value = Math.min(3, zoomLevel.value + 0.25); | 255 | zoomLevel.value = Math.min(3, zoomLevel.value + 0.25); |
| 256 | + const newZoom = zoomLevel.value; | ||
| 257 | + | ||
| 258 | + // 使用nextTick确保DOM更新后再调整滚动位置 | ||
| 259 | + nextTick(() => { | ||
| 260 | + const zoomRatio = newZoom / oldZoom; | ||
| 261 | + const newScrollLeft = centerX * zoomRatio - pdfContainer.clientWidth / 2; | ||
| 262 | + const newScrollTop = centerY * zoomRatio - pdfContainer.clientHeight / 2; | ||
| 263 | + | ||
| 264 | + pdfContainer.scrollTo({ | ||
| 265 | + left: Math.max(0, newScrollLeft), | ||
| 266 | + top: Math.max(0, newScrollTop), | ||
| 267 | + behavior: 'smooth' | ||
| 268 | + }); | ||
| 269 | + }); | ||
| 270 | + } | ||
| 241 | } | 271 | } |
| 242 | }; | 272 | }; |
| 243 | 273 | ||
| ... | @@ -246,7 +276,29 @@ const zoomIn = () => { | ... | @@ -246,7 +276,29 @@ const zoomIn = () => { |
| 246 | */ | 276 | */ |
| 247 | const zoomOut = () => { | 277 | const zoomOut = () => { |
| 248 | if (zoomLevel.value > 0.5) { // 最小缩小到50% | 278 | if (zoomLevel.value > 0.5) { // 最小缩小到50% |
| 279 | + // 记录缩放前的滚动位置 | ||
| 280 | + const pdfContainer = document.querySelector('.pdf-viewer-container .pdf-content'); | ||
| 281 | + if (pdfContainer) { | ||
| 282 | + const centerX = pdfContainer.scrollLeft + pdfContainer.clientWidth / 2; | ||
| 283 | + const centerY = pdfContainer.scrollTop + pdfContainer.clientHeight / 2; | ||
| 284 | + | ||
| 285 | + const oldZoom = zoomLevel.value; | ||
| 249 | zoomLevel.value = Math.max(0.5, zoomLevel.value - 0.25); | 286 | zoomLevel.value = Math.max(0.5, zoomLevel.value - 0.25); |
| 287 | + const newZoom = zoomLevel.value; | ||
| 288 | + | ||
| 289 | + // 使用nextTick确保DOM更新后再调整滚动位置 | ||
| 290 | + nextTick(() => { | ||
| 291 | + const zoomRatio = newZoom / oldZoom; | ||
| 292 | + const newScrollLeft = centerX * zoomRatio - pdfContainer.clientWidth / 2; | ||
| 293 | + const newScrollTop = centerY * zoomRatio - pdfContainer.clientHeight / 2; | ||
| 294 | + | ||
| 295 | + pdfContainer.scrollTo({ | ||
| 296 | + left: Math.max(0, newScrollLeft), | ||
| 297 | + top: Math.max(0, newScrollTop), | ||
| 298 | + behavior: 'smooth' | ||
| 299 | + }); | ||
| 300 | + }); | ||
| 301 | + } | ||
| 250 | } | 302 | } |
| 251 | }; | 303 | }; |
| 252 | 304 | ||
| ... | @@ -254,7 +306,21 @@ const zoomOut = () => { | ... | @@ -254,7 +306,21 @@ const zoomOut = () => { |
| 254 | * 重置缩放 | 306 | * 重置缩放 |
| 255 | */ | 307 | */ |
| 256 | const resetZoom = () => { | 308 | const resetZoom = () => { |
| 309 | + const pdfContainer = document.querySelector('.pdf-viewer-container .pdf-content'); | ||
| 310 | + if (pdfContainer) { | ||
| 311 | + // 重置到顶部中央位置 | ||
| 257 | zoomLevel.value = 1; | 312 | zoomLevel.value = 1; |
| 313 | + | ||
| 314 | + nextTick(() => { | ||
| 315 | + pdfContainer.scrollTo({ | ||
| 316 | + left: 0, | ||
| 317 | + top: 0, | ||
| 318 | + behavior: 'smooth' | ||
| 319 | + }); | ||
| 320 | + }); | ||
| 321 | + } else { | ||
| 322 | + zoomLevel.value = 1; | ||
| 323 | + } | ||
| 258 | }; | 324 | }; |
| 259 | 325 | ||
| 260 | /** | 326 | /** | ... | ... |
-
Please register or login to post a comment