优化pdf 搜索
This commit is contained in:
parent
4aa85dbf7b
commit
f5ae85453c
|
|
@ -362,12 +362,17 @@ export default {
|
||||||
const viewport = page.getViewport({ scale: this.scale })
|
const viewport = page.getViewport({ scale: this.scale })
|
||||||
// 渲染时允许更新尺寸(如果 viewport 与预设不同)
|
// 渲染时允许更新尺寸(如果 viewport 与预设不同)
|
||||||
this.ensureContainerDimensions(pageNumber, viewport, true)
|
this.ensureContainerDimensions(pageNumber, viewport, true)
|
||||||
container.classList.add('is-loading')
|
|
||||||
|
// 先移除旧 canvas(如果存在)
|
||||||
const oldCanvas = container.querySelector('.pdf-canvas')
|
const oldCanvas = container.querySelector('.pdf-canvas')
|
||||||
if (oldCanvas) {
|
if (oldCanvas) {
|
||||||
oldCanvas.remove()
|
oldCanvas.remove()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加 is-loading 类并显示 loading
|
||||||
|
container.classList.add('is-loading')
|
||||||
|
// 确保显示 loading 图标
|
||||||
|
this.showPageLoading(container)
|
||||||
|
|
||||||
const canvas = document.createElement('canvas')
|
const canvas = document.createElement('canvas')
|
||||||
canvas.className = 'pdf-canvas'
|
canvas.className = 'pdf-canvas'
|
||||||
|
|
@ -405,6 +410,8 @@ export default {
|
||||||
|
|
||||||
this.renderedPages.set(pageNumber, { container, viewport })
|
this.renderedPages.set(pageNumber, { container, viewport })
|
||||||
container.classList.remove('is-loading')
|
container.classList.remove('is-loading')
|
||||||
|
// canvas 渲染完成,隐藏 loading
|
||||||
|
this.hidePageLoading(container)
|
||||||
return { page, viewport, container }
|
return { page, viewport, container }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -475,6 +482,8 @@ export default {
|
||||||
const container = this.pageContainers[pageNumber - 1]
|
const container = this.pageContainers[pageNumber - 1]
|
||||||
if (container) {
|
if (container) {
|
||||||
container.classList.add('is-loading', 'is-loading-text')
|
container.classList.add('is-loading', 'is-loading-text')
|
||||||
|
// 显示 loading
|
||||||
|
this.showPageLoading(container)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await this.renderTextLayer(pageNumber, { visible: true, force: true })
|
await this.renderTextLayer(pageNumber, { visible: true, force: true })
|
||||||
|
|
@ -489,6 +498,13 @@ export default {
|
||||||
scheduleRender(pageNumber, { priority = false } = {}) {
|
scheduleRender(pageNumber, { priority = false } = {}) {
|
||||||
if (!pageNumber || pageNumber > this.totalPages || this.renderedPages.has(pageNumber)) return
|
if (!pageNumber || pageNumber > this.totalPages || this.renderedPages.has(pageNumber)) return
|
||||||
if (this.renderQueue.includes(pageNumber)) return
|
if (this.renderQueue.includes(pageNumber)) return
|
||||||
|
|
||||||
|
// 在加入渲染队列时显示 loading
|
||||||
|
const container = this.pageContainers[pageNumber - 1]
|
||||||
|
if (container && !container.querySelector('.pdf-canvas')) {
|
||||||
|
this.showPageLoading(container)
|
||||||
|
}
|
||||||
|
|
||||||
if (priority) {
|
if (priority) {
|
||||||
this.renderQueue.unshift(pageNumber)
|
this.renderQueue.unshift(pageNumber)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1146,6 +1162,11 @@ export default {
|
||||||
if (entry.isIntersecting) {
|
if (entry.isIntersecting) {
|
||||||
const page = Number(entry.target.dataset.page)
|
const page = Number(entry.target.dataset.page)
|
||||||
if (page) {
|
if (page) {
|
||||||
|
const container = entry.target
|
||||||
|
// 如果页面还未渲染,显示 loading
|
||||||
|
if (!this.renderedPages.has(page) && !container.querySelector('.pdf-canvas')) {
|
||||||
|
this.showPageLoading(container)
|
||||||
|
}
|
||||||
this.renderTextLayer(page, { visible: true, force: true })
|
this.renderTextLayer(page, { visible: true, force: true })
|
||||||
this.scheduleRender(page, { priority: true })
|
this.scheduleRender(page, { priority: true })
|
||||||
}
|
}
|
||||||
|
|
@ -1180,6 +1201,127 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showPageLoading(container) {
|
||||||
|
if (!container) return
|
||||||
|
const pageNumber = Number(container.dataset.page)
|
||||||
|
|
||||||
|
// 如果页面已经渲染完成,不显示 loading
|
||||||
|
if (pageNumber && this.renderedPages.has(pageNumber)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否已经有 canvas,如果有则不显示 loading(表示已经渲染完成)
|
||||||
|
const existingCanvas = container.querySelector('.pdf-canvas')
|
||||||
|
if (existingCanvas) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果已经有 loading 在显示,不重复创建
|
||||||
|
const existingLoading = container.querySelector('.page-loading-wrapper')
|
||||||
|
if (existingLoading && getComputedStyle(existingLoading).display !== 'none') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保容器有尺寸,如果没有则设置最小高度
|
||||||
|
const containerHeight = container.offsetHeight || parseInt(container.style.height) || 0
|
||||||
|
const containerWidth = container.offsetWidth || parseInt(container.style.width) || 0
|
||||||
|
|
||||||
|
if (containerHeight < 100 || containerWidth < 100) {
|
||||||
|
// 尝试从缓存中获取 viewport 来设置尺寸
|
||||||
|
if (this.pageCache.has(pageNumber)) {
|
||||||
|
try {
|
||||||
|
const page = this.pageCache.get(pageNumber)
|
||||||
|
const viewport = page.getViewport({ scale: this.scale })
|
||||||
|
container.style.width = `${viewport.width}px`
|
||||||
|
container.style.height = `${viewport.height}px`
|
||||||
|
} catch (e) {
|
||||||
|
// 如果获取失败,设置最小尺寸
|
||||||
|
if (!container.style.width) container.style.width = '800px'
|
||||||
|
if (!container.style.height) container.style.minHeight = '1000px'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果没有缓存,设置默认尺寸
|
||||||
|
if (!container.style.width) container.style.width = '800px'
|
||||||
|
if (!container.style.height) container.style.minHeight = '1000px'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保容器是 relative 定位
|
||||||
|
if (getComputedStyle(container).position === 'static') {
|
||||||
|
container.style.position = 'relative'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建或获取 loading 容器和图标
|
||||||
|
let loadingWrapper = container.querySelector('.page-loading-wrapper')
|
||||||
|
if (!loadingWrapper) {
|
||||||
|
loadingWrapper = document.createElement('div')
|
||||||
|
loadingWrapper.className = 'page-loading-wrapper'
|
||||||
|
|
||||||
|
const loadingIcon = document.createElement('i')
|
||||||
|
loadingIcon.className = 'el-icon-loading page-loading-icon'
|
||||||
|
loadingWrapper.appendChild(loadingIcon)
|
||||||
|
|
||||||
|
container.appendChild(loadingWrapper)
|
||||||
|
} else {
|
||||||
|
// 如果已存在,确保图标也存在
|
||||||
|
let loadingIcon = loadingWrapper.querySelector('.page-loading-icon')
|
||||||
|
if (!loadingIcon) {
|
||||||
|
loadingIcon = document.createElement('i')
|
||||||
|
loadingIcon.className = 'el-icon-loading page-loading-icon'
|
||||||
|
loadingWrapper.appendChild(loadingIcon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 强制设置所有样式,确保显示 - 简单的灰色旋转图标
|
||||||
|
loadingWrapper.style.cssText = `
|
||||||
|
position: absolute !important;
|
||||||
|
top: 33% !important;
|
||||||
|
left: 50% !important;
|
||||||
|
transform: translate(-50%, -50%) !important;
|
||||||
|
z-index: 1000 !important;
|
||||||
|
display: flex !important;
|
||||||
|
visibility: visible !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
align-items: center !important;
|
||||||
|
justify-content: center !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
`
|
||||||
|
|
||||||
|
// 确保图标样式和动画启动
|
||||||
|
const icon = loadingWrapper.querySelector('.page-loading-icon')
|
||||||
|
if (icon) {
|
||||||
|
icon.style.cssText = `
|
||||||
|
font-size: 24px !important;
|
||||||
|
color: #909399 !important;
|
||||||
|
display: block !important;
|
||||||
|
animation: pdf-page-spin 1s linear infinite !important;
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 requestAnimationFrame 确保动画能正常启动
|
||||||
|
this.$nextTick(() => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
if (loadingWrapper && loadingWrapper.parentNode) {
|
||||||
|
// 触发重排,确保动画开始
|
||||||
|
void loadingWrapper.offsetHeight
|
||||||
|
// 确保图标动画也启动
|
||||||
|
if (icon) {
|
||||||
|
// 强制重新应用动画
|
||||||
|
icon.style.animation = 'none'
|
||||||
|
void icon.offsetHeight
|
||||||
|
icon.style.setProperty('animation', 'pdf-page-spin 1s linear infinite', 'important')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
hidePageLoading(container) {
|
||||||
|
if (!container) return
|
||||||
|
const loadingWrapper = container.querySelector('.page-loading-wrapper')
|
||||||
|
if (loadingWrapper) {
|
||||||
|
loadingWrapper.style.setProperty('display', 'none', 'important')
|
||||||
|
}
|
||||||
|
},
|
||||||
disconnectObserver() {
|
disconnectObserver() {
|
||||||
if (this.observer) {
|
if (this.observer) {
|
||||||
this.observer.disconnect()
|
this.observer.disconnect()
|
||||||
|
|
@ -1464,6 +1606,36 @@ export default {
|
||||||
letter-spacing: 0.4px;
|
letter-spacing: 0.4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page-loading-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 33%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 100;
|
||||||
|
display: none;
|
||||||
|
pointer-events: none;
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-loading-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #909399;
|
||||||
|
animation: pdf-page-spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pdf-page.placeholder .page-loading-wrapper,
|
||||||
|
.pdf-page.prefetched .page-loading-wrapper,
|
||||||
|
.pdf-page.is-loading .page-loading-wrapper,
|
||||||
|
.pdf-page[data-status="placeholder"] .page-loading-wrapper,
|
||||||
|
.pdf-page[data-status="prefetched"] .page-loading-wrapper,
|
||||||
|
.pdf-page[data-status="text-ready"] .page-loading-wrapper,
|
||||||
|
.pdf-page .page-loading-wrapper[style*="display: flex"] {
|
||||||
|
display: flex !important;
|
||||||
|
}
|
||||||
|
|
||||||
.pdf-canvas {
|
.pdf-canvas {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue