Skip to content

PDFViewer PDF 预览

PDF 文件预览组件,基于 pdfjs-dist 封装。支持 URL 和 ArrayBuffer 两种数据源,内置完整的工具栏(翻页、缩放、旋转、缩略图),支持 OCR 标注叠加和高亮跳转。

默认禁用功能: 为优化性能,组件默认关闭了文本选择、全文搜索、注释编辑、打印等功能。如有需要可在 config.ts 中调整 textLayerModeannotationMode 等选项。

基础用法

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

属性名类型默认值说明
urlstring | ArrayPDF 文件 URL(或数组)
dataArrayBufferPDF 数据的 ArrayBuffer,与 url 二选一
srcListstring[]图片源列表(与 ImageOcrViewer 保持一致)
ocrListOcrPageData[]OCR 标注数据,叠加在 PDF 上
defaultFirstSelectedbooleantrue是否默认选中第一个 OCR 标注
showHighlightbooleantrue是否显示 OCR 标注高亮工具栏
onReady(opt: { application, options }) => voidPDF 加载完成回调
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

属性类型说明
widthnumber页面宽度
heightnumber页面高度
anglenumber旋转角度
pageNumbernumber页码(从 1 开始)
dataOcrRect[]当前页的所有标注框

OcrRect

属性类型说明
positionnumber[]坐标数组 [x1, y1, x2, y2, ...]
textstring识别文本内容
intoViewPointsstring用于定位的 viewPoints 字符串
pointsstring多边形坐标点字符串
keystring?唯一标识
nextOcrRect?下一个标注(由组件内部自动串联)
prevOcrRect?上一个标注(由组件内部自动串联)
indexnumber?序号(由组件内部自动编号)
pageNumbernumber?所在页码(从 0 开始)
datasetRecord<string, any>?自定义数据
propsRecord<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)