文档加载优化

This commit is contained in:
cwchen 2025-11-11 10:00:08 +08:00
parent 2417dd974d
commit 325719c7bc
1 changed files with 74 additions and 15 deletions

View File

@ -81,10 +81,6 @@ export default {
}
return null
},
isAtLastResult() {
if (!this.searchResults.length) return true
return this.currentResultIndex >= this.searchResults.length - 1
},
},
data() {
return {
@ -115,6 +111,7 @@ export default {
standardFontDataUrl: '',
pdfAssetsBase: '',
searching: false,
scrollAnimationFrame: null,
}
},
mounted() {
@ -144,6 +141,7 @@ export default {
},
beforeDestroy() {
this.disconnectObserver()
this.cancelScrollAnimation()
},
watch: {
'$route.query.url'(newUrl, oldUrl) {
@ -300,10 +298,13 @@ export default {
const renderContext = {
canvasContext,
viewport,
transform: [outputScale, 0, 0, outputScale, 0, 0],
intent: 'print',
enableWebGL: true,
background: 'rgba(255,255,255,0)',
}
if (outputScale !== 1) {
renderContext.transform = [outputScale, 0, 0, outputScale, 0, 0]
}
canvasContext.setTransform(outputScale, 0, 0, outputScale, 0, 0)
canvasContext.imageSmoothingEnabled = false
await page.render(renderContext).promise
container.dataset.status = 'rendered'
@ -746,7 +747,8 @@ export default {
await this.renderTextLayer(pageNumber, { visible: true, force: true })
await this.renderCanvas(pageNumber)
await this.$nextTick()
this.highlightMatches({ preserveIndex: true, skipNavigate: true })
this.applyHighlightsToPage(pageNumber - 1)
this.scheduleActiveHighlightRefresh()
}
this.currentResultIndex = index
@ -758,13 +760,12 @@ export default {
if (!wrapper) return
this.$nextTick(() => {
const targetRect = target.getBoundingClientRect()
const wrapperRect = wrapper.getBoundingClientRect()
const offset = targetRect.top - wrapperRect.top - wrapper.clientHeight / 2
wrapper.scrollTo({
top: wrapper.scrollTop + offset,
behavior: 'smooth'
})
const container = target.closest('.pdf-page') || target
if (!container) return
const wrapperOffsetTop = container.offsetTop
const containerHeight = container.offsetHeight || target.offsetHeight || 0
const desired = wrapperOffsetTop - Math.max((wrapper.clientHeight - containerHeight) / 2, 0)
this.smoothScrollTo(wrapper, desired)
})
},
@ -887,6 +888,51 @@ export default {
})
},
cancelScrollAnimation() {
if (this.scrollAnimationFrame !== null && typeof window !== 'undefined') {
cancelAnimationFrame(this.scrollAnimationFrame)
this.scrollAnimationFrame = null
}
},
smoothScrollTo(container, target, baseDuration = 240) {
if (!container) return
const maxScroll = container.scrollHeight - container.clientHeight
const finalTarget = Math.min(Math.max(target, 0), Math.max(maxScroll, 0))
const start = container.scrollTop
const change = finalTarget - start
if (Math.abs(change) < 1) {
container.scrollTop = finalTarget
return
}
const distanceFactor = Math.min(Math.abs(change) / Math.max(container.clientHeight, 1), 2.4)
const duration = Math.min(460, baseDuration + distanceFactor * 110)
const startTime = performance.now()
const ease = (t) => 1 - Math.pow(1 - t, 4)
const velocityBoost = Math.min(Math.max(Math.abs(change) / 2400, 0), 0.25)
this.cancelScrollAnimation()
const step = (now) => {
const elapsed = now - startTime
const progress = Math.min(elapsed / duration, 1)
const eased = ease(progress)
const basePosition = start + change * eased
const overshoot = velocityBoost * Math.sin(eased * Math.PI)
container.scrollTop = Math.min(Math.max(basePosition + overshoot * change, 0), maxScroll)
if (progress < 1) {
this.scrollAnimationFrame = requestAnimationFrame(step)
} else {
this.scrollAnimationFrame = null
}
}
this.scrollAnimationFrame = requestAnimationFrame(step)
},
goToPrevious() {
if (!this.searchResults.length) return
let targetIndex = this.currentResultIndex
@ -948,6 +994,7 @@ export default {
this.disconnectObserver()
this.cancelPrefetch()
this.pageCache.clear()
this.cancelScrollAnimation()
const wrapper = this.$refs.pdfWrapper
if (wrapper) {
wrapper.innerHTML = ''
@ -1040,6 +1087,13 @@ export default {
background: #f4f7ff;
padding: 16px;
box-sizing: border-box;
font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Arial, sans-serif;
font-size: 14px;
line-height: 1.6;
color: #1f2430;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
.search-toolbar {
@ -1096,6 +1150,10 @@ export default {
// background: linear-gradient(180deg, #eef3ff 0%, #ffffff 100%);
background: #eaeaea;
position: relative;
scroll-behavior: smooth;
overscroll-behavior: contain;
scrollbar-gutter: stable both-edges;
-webkit-overflow-scrolling: touch;
}
.pdf-page {
@ -1106,6 +1164,7 @@ export default {
overflow: hidden;
background: #ffffff;
display: block;
will-change: transform, opacity;
}
.pdf-page:first-of-type::before,