Skip to content

ImageOcrViewer 图片 OCR 预览

图片预览组件,支持在图片上叠加 OCR 识别结果框选,提供标注切换、缩放、旋转等操作。

基础用法

tsx
import { defineComponent, defineAsyncComponent, ref, shallowRef } from 'vue'
import { ElButton, ElMessage } from 'element-plus'

const AsyncViewer = defineAsyncComponent(() => import('@/components/ImageOcrViewer'))

// OCR 数据,position 格式为 [x1,y1, x2,y2, x3,y3, x4,y4]
// 根据 bg.webp 实际尺寸(1920×1080)调整标注位置
const sampleOcrData = [
  {
    width: 1920,
    height: 1080,
    angle: 0,
    pageNumber: 0,
    data: [
      {
        text: '标题区域:ImageOcrViewer 图片 OCR 预览演示',
        position: [200, 150, 1200, 150, 1200, 220, 200, 220],
        dataset: { section: 'title' },
      },
      {
        text: '段落一:该组件支持在图片上叠加 OCR 识别框选',
        position: [200, 300, 1400, 300, 1400, 370, 200, 370],
        dataset: { section: 'p1' },
      },
      {
        text: '段落二:点击矩形框可选中,使用上下按钮切换高亮',
        position: [200, 420, 1300, 420, 1300, 490, 200, 490],
        dataset: { section: 'p2' },
      },
      {
        text: '段落三:可通过 dataset 字段实现精准跳转',
        position: [200, 540, 1100, 540, 1100, 610, 200, 610],
        dataset: { section: 'p3' },
      },
      {
        text: '底部标注区域',
        position: [400, 700, 900, 700, 900, 770, 400, 770],
        dataset: { section: 'footer' },
      },
    ],
  },
]

export default defineComponent({
  name: 'DemoImageOcrViewerBasic',
  setup() {
    const viewerRef = ref<any>(null)
    const currentRect = ref<any>(null)
    const showOcr = ref(true)
    const ocrList = shallowRef(sampleOcrData)

    const handleCurrentChange = (rect: any) => {
      currentRect.value = rect
    }

    const jumpToSection = (section: string) => {
      viewerRef.value?.select?.('section', section)
    }

    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={() => jumpToSection('title')}>
              跳转标题
            </ElButton>
            <ElButton size="small" onClick={() => jumpToSection('p2')}>
              跳转段落二
            </ElButton>
            <ElButton size="small" onClick={() => jumpToSection('footer')}>
              跳转底部
            </ElButton>
            <ElButton
              size="small"
              onClick={() => {
                showOcr.value = !showOcr.value
                ocrList.value = showOcr.value ? sampleOcrData : []
              }}
            >
              {showOcr.value ? '隐藏' : '显示'} OCR
            </ElButton>
            <span style="font-size:13px; color:#909399;">
              {currentRect.value
                ? `当前:${currentRect.value.text}`
                : '点击标注矩形可选中'}
            </span>
          </div>

          <div style="border:1px solid var(--vp-c-divider); border-radius:4px; overflow:hidden;">
            <AsyncViewer
              ref={viewerRef}
              url="/yoyoo-ui/bg.webp"
              ocrList={ocrList.value as any}
              showHighlight={true}
              defaultFirstSelected={true}
              style="height:600px"
              onCurrentChange={handleCurrentChange}
              onError={(e: any) => ElMessage.error('图片加载失败')}
            />
          </div>

          <div style="font-size:13px; color:#909399; line-height:1.6;">
            <strong>直接跳转:</strong>在 OCR 数据的 <code>dataset</code> 中定义自定义字段(如 <code>section</code>),
            然后通过 <code>viewerRef.select('section', 'p2')</code> 即可跳转到对应标注。
          </div>

        </div>
      </div>
    )
  },
})

Props

属性名类型默认值说明
urlstring图片地址
ocrListOcrPageData[]OCR 识别数据,包含位置信息
defaultFirstSelectedbooleantrue是否默认选中第一个 OCR 标注
showHighlightbooleantrue是否显示标注导航工具栏
onDownload(url: string) => void下载原图回调
onDowload(url: string) => void兼容旧版拼写的下载回调
onError(error) => void加载失败回调
onCurrentChange(rect: OcrRect) => void当前选中标注变化时触发

Expose 方法

通过 ref 可调用以下方法:

方法签名说明
prev() => void上一个 OCR 标注
next() => void下一个 OCR 标注
select(propKey: string, value: any) => void根据 dataset 字段跳转到对应标注

select 直接跳转

select 方法通过 OCR 数据中 dataset 的自定义字段定位标注:

tsx
const viewerRef = ref()

// OCR 数据中定义 dataset
const ocrData = [{
  width: 800, height: 600, angle: 0, pageNumber: 0,
  data: [
    {
      text: '标题',
      position: [80, 80, 580, 80, 580, 140, 80, 140],
      dataset: { section: 'title' },  // 自定义标识
    },
    {
      text: '段落二',
      position: [80, 260, 560, 260, 560, 310, 80, 310],
      dataset: { section: 'p2' },     // 自定义标识
    },
  ],
}]

// 跳转到 section 为 'p2' 的标注
viewerRef.value?.select('section', 'p2')

OCR 数据格式

OcrPageData

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

OcrRect

属性类型说明
positionnumber[]坐标数组 [x1, y1, x2, y2, x3, y3, x4, y4],定义矩形四个角
textstring识别文本内容
datasetRecord<string, any>?自定义数据,用于 select() 方法精准跳转
keystring?唯一标识(由组件内部生成)
nextOcrRect?下一个标注(由组件内部自动串联)
prevOcrRect?上一个标注(由组件内部自动串联)
indexnumber?序号(由组件内部自动编号)
pageNumbernumber?所在页码
propsRecord<string, any>?自定义属性,透传到 SVG polygon 元素

nextprevindexkey 由组件内部自动处理,传入时不需要提供。

内置功能

功能说明
标注导航上下切换高亮标注,显示当前序号
直接跳转通过 dataset 字段 + select() 方法快速定位
缩放放大/缩小(鼠标滚轮或按钮),范围 20%~500%
旋转左旋/右旋 90°,自动适配视口
下载下载原图
鼠标拖拽拖拽滚动图片
键盘快捷键缩放(Ctrl+±)、旋转(Ctrl+[ / ])、适应页面(Ctrl+0)