diff --git a/src/views/common/DocumentSearch.vue b/src/views/common/DocumentSearch.vue index 7f6eaab..263bff3 100644 --- a/src/views/common/DocumentSearch.vue +++ b/src/views/common/DocumentSearch.vue @@ -515,7 +515,16 @@ export default { try { while (this.renderQueue.length) { const pageNumber = this.renderQueue.shift() - await new Promise((resolve) => requestAnimationFrame(resolve)) + // 使用 requestIdleCallback 优化性能,在浏览器空闲时渲染 + if (typeof window.requestIdleCallback === 'function') { + await new Promise((resolve) => { + window.requestIdleCallback(() => { + requestAnimationFrame(resolve) + }, { timeout: 100 }) + }) + } else { + await new Promise((resolve) => requestAnimationFrame(resolve)) + } await this.renderSinglePage(pageNumber) } } finally { @@ -551,9 +560,11 @@ export default { const schedule = () => { this.prefetchScheduled = true if (typeof window.requestIdleCallback === 'function') { - this.prefetchHandle = window.requestIdleCallback(fetchNext, { timeout: 1000 }) + // 增加超时时间,减少对滚动的影响 + this.prefetchHandle = window.requestIdleCallback(fetchNext, { timeout: 2000 }) } else { - this.prefetchHandle = window.setTimeout(fetchNext, 80) + // 增加延迟,减少对滚动的影响 + this.prefetchHandle = window.setTimeout(fetchNext, 150) } } schedule() @@ -565,10 +576,10 @@ export default { this.isPrefetching = true if (typeof window.requestIdleCallback === 'function') { this.prefetchScheduled = true - this.prefetchHandle = window.requestIdleCallback(fetchNext, { timeout: 800 }) + this.prefetchHandle = window.requestIdleCallback(fetchNext, { timeout: 1500 }) } else { this.prefetchScheduled = true - this.prefetchHandle = window.setTimeout(fetchNext, 120) + this.prefetchHandle = window.setTimeout(fetchNext, 200) } }, @@ -1211,11 +1222,19 @@ export default { const options = { root: this.$refs.pdfWrapper, - rootMargin: '120px 0px', - threshold: 0.01, + rootMargin: '200px 0px', // 增加预加载范围,减少滚动时的加载延迟 + threshold: [0, 0.1, 0.5, 1], // 使用多个阈值,更精确地检测可见性 } - this.observer = new IntersectionObserver((entries) => { + // 使用 requestAnimationFrame 批量处理 IntersectionObserver 回调,提升性能 + let rafScheduled = false + const pendingEntries = [] + + const processEntries = () => { + rafScheduled = false + const entries = [...pendingEntries] + pendingEntries.length = 0 + entries.forEach((entry) => { if (entry.isIntersecting) { const page = Number(entry.target.dataset.page) @@ -1235,6 +1254,14 @@ export default { } } }) + } + + this.observer = new IntersectionObserver((entries) => { + pendingEntries.push(...entries) + if (!rafScheduled) { + rafScheduled = true + requestAnimationFrame(processEntries) + } }, options) this.pageContainers.forEach((container) => this.observer.observe(container)) @@ -1597,6 +1624,8 @@ export default { scrollbar-gutter: stable both-edges; -webkit-overflow-scrolling: touch; overflow-x: auto; + /* 性能优化 */ + will-change: scroll-position; } .pdf-page { @@ -1697,6 +1726,10 @@ export default { .pdf-canvas { display: block; margin: 0 auto; + /* 性能优化 */ + image-rendering: -webkit-optimize-contrast; + image-rendering: crisp-edges; + will-change: contents; } .textLayer { @@ -1708,6 +1741,8 @@ export default { pointer-events: auto; user-select: text; -webkit-user-select: text; + /* 性能优化 */ + will-change: contents; } .textLayer>span {