文档加载优化
This commit is contained in:
parent
2417dd974d
commit
325719c7bc
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue