Appearance
PDFViewer PDF 预览
PDF 文件预览组件,基于 pdfjs-dist 封装。支持 URL 和 ArrayBuffer 两种数据源,内置完整的工具栏(翻页、缩放、旋转、缩略图),支持 OCR 标注叠加和高亮跳转。
默认禁用功能: 为优化性能,组件默认关闭了文本选择、全文搜索、注释编辑、打印等功能。如有需要可在
config.ts中调整textLayerMode、annotationMode等选项。
基础用法
tsx
import { defineComponent, defineAsyncComponent, ref } from 'vue'
import { ElButton } from 'element-plus'
import { ElMessage as message } from 'element-plus'
const AsyncPDFViewer = defineAsyncComponent(() => import('@/components/PDFViewer'))
// 示例 OCR 数据 — 与 demo.pdf 页面尺寸匹配
const sampleOcrData = [
{
width: 595,
height: 842,
angle: 0,
pageNumber: 1,
data: [
{ position: [80, 120, 400, 120, 400, 150, 80, 150], text: 'PDF 文档标题区域', key: 'k1' },
{ position: [80, 200, 300, 200, 300, 230, 80, 230], text: '段落一:这是一段示例文本内容', key: 'k2' },
{ position: [80, 260, 480, 260, 480, 290, 80, 290], text: '段落二:PDFViewer 支持 OCR 标注叠加和高亮跳转', key: 'k3' },
{ position: [80, 320, 350, 320, 350, 350, 80, 350], text: '段落三:可自定义标注颜色和样式', key: 'k4' },
],
},
{
width: 595,
height: 842,
angle: 0,
pageNumber: 2,
data: [
{ position: [80, 150, 450, 150, 450, 180, 80, 180], text: '第二页标题', key: 'k5' },
{ position: [80, 230, 400, 230, 400, 260, 80, 260], text: '第二页正文内容示例', key: 'k6' },
],
},
]
export default defineComponent({
name: 'DemoPDFViewerBasic',
setup() {
const viewerRef = ref<any>(null)
const currentRect = ref<any>(null)
const showOcr = ref(true)
const handleReady = () => {
message.success('PDF 加载完成')
}
const handleError = () => {
message.error('PDF 加载失败')
}
const handleCurrentChange = (rect: any) => {
currentRect.value = rect
}
return () => (
<div class="demo-block">
<div style="display:flex; flex-direction:column; gap:16px;">
<div style="display:flex; gap:8px; align-items:center; flex-wrap:wrap;">
<ElButton size="small" onClick={() => viewerRef.value?.prev?.()}>
上一个标注
</ElButton>
<ElButton size="small" onClick={() => viewerRef.value?.next?.()}>
下一个标注
</ElButton>
<ElButton size="small" onClick={() => { showOcr.value = !showOcr.value }}>
{showOcr.value ? '隐藏' : '显示'} OCR
</ElButton>
<span style="font-size:13px; color:#909399;">
{currentRect.value
? `当前:${currentRect.value.text}`
: '点击标注矩形可选中'}
</span>
</div>
<div style="height:600px; border:1px solid var(--vp-c-divider); border-radius:4px; overflow:hidden;">
<AsyncPDFViewer
ref={viewerRef}
url="/yoyoo-ui/demo.pdf"
style="width:100%; height:100%;"
ocrList={showOcr.value ? sampleOcrData as any : []}
showHighlight={true}
defaultFirstSelected={true}
onReady={handleReady}
onError={handleError}
onCurrentChange={handleCurrentChange}
/>
</div>
</div>
</div>
)
},
})Props
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| url | string | Array | — | PDF 文件 URL(或数组) |
| data | ArrayBuffer | — | PDF 数据的 ArrayBuffer,与 url 二选一 |
| srcList | string[] | — | 图片源列表(与 ImageOcrViewer 保持一致) |
| ocrList | OcrPageData[] | — | OCR 标注数据,叠加在 PDF 上 |
| defaultFirstSelected | boolean | true | 是否默认选中第一个 OCR 标注 |
| showHighlight | boolean | true | 是否显示 OCR 标注高亮工具栏 |
| onReady | (opt: { application, options }) => void | — | PDF 加载完成回调 |
| onError | (error) => void | — | 加载失败回调 |
| onDownload | (url: string) => void | — | 下载回调 |
| onCurrentChange | (rect: OcrRect) => void | — | 当前选中 OCR 标注变化时触发 |
数据源
组件支持两种数据源方式,二选一:
URL 方式
tsx
<PDFViewer url="https://example.com/document.pdf" />ArrayBuffer 方式
tsx
const buffer = await fetch(url).then((res) => res.arrayBuffer())
<PDFViewer :data={buffer} />Expose 方法
通过 ref 可调用以下方法:
| 方法 | 签名 | 说明 |
|---|---|---|
| prev | () => void | 上一个 OCR 高亮 |
| next | () => void | 下一个 OCR 高亮 |
| select | (propKey: string, value: any) => void | 根据 OCR 数据的某个字段值跳转到对应标注 |
| gotoPage | (pageNumber: number) => void | 跳转到指定页(从 1 开始) |
tsx
const viewerRef = ref()
// 跳转到第 5 页
viewerRef.value?.gotoPage(5)OCR 标注叠加
通过 ocrList 传入 OCR 识别结果的页面数据,组件会在 PDF 上叠加矩形框选标注,并支持上下切换高亮:
tsx
<PDFViewer
url="https://example.com/document.pdf"
:ocrList={ocrData}
:showHighlight={true}
:defaultFirstSelected={true}
@currentChange="handleRectChange"
/>OcrPageData
| 属性 | 类型 | 说明 |
|---|---|---|
| width | number | 页面宽度 |
| height | number | 页面高度 |
| angle | number | 旋转角度 |
| pageNumber | number | 页码(从 1 开始) |
| data | OcrRect[] | 当前页的所有标注框 |
OcrRect
| 属性 | 类型 | 说明 |
|---|---|---|
| position | number[] | 坐标数组 [x1, y1, x2, y2, ...] |
| text | string | 识别文本内容 |
| intoViewPoints | string | 用于定位的 viewPoints 字符串 |
| points | string | 多边形坐标点字符串 |
| key | string? | 唯一标识 |
| next | OcrRect? | 下一个标注(由组件内部自动串联) |
| prev | OcrRect? | 上一个标注(由组件内部自动串联) |
| index | number? | 序号(由组件内部自动编号) |
| pageNumber | number? | 所在页码(从 0 开始) |
| dataset | Record<string, any>? | 自定义数据 |
| props | Record<string, any>? | 自定义属性 |
示例数据
json
[
{
"width": 2480,
"height": 3508,
"angle": 0,
"pageNumber": 1,
"data": [
{
"position": [100, 200, 500, 200, 500, 300, 100, 300],
"text": "识别文本内容",
"key": "rect_1_0"
}
]
}
]next / prev / index 字段由组件内部的 useMergedOcrRects 自动串联和编号,传入时不需要提供。
内置功能
PDFViewer 基于 pdfjs-viewer-dom 提供了完整的 PDF 阅读体验:
| 功能 | 说明 |
|---|---|
| 页面导航 | 上一页/下一页、输入页码跳转、首尾页 |
| 缩放 | 放大、缩小、自动/实际大小/适合页面/适合宽度 |
| 旋转 | 左旋 90°、右旋 90° |
| 侧边栏 | 缩略图预览、大纲(如 PDF 包含目录) |
| 搜索 | 全文搜索(需开启 textLayerMode) |
| OCR 高亮 | 上下切换高亮标注、跳转对应页面 |
| 鼠标拖拽 | 拖拽滚动页面 |
| 键盘快捷键 | 缩放(Ctrl+±)、旋转(Ctrl+[ / ])、适合页面(Ctrl+0) |