vue3-image-annotation

Vue 3 image annotation component based on fabric.js — draw rect / circle / polygon annotations on images with zoom, undo/redo, echo and PNG export. 基于 fabric.js 的 Vue3 在线图片标注组件
173 1
Install
npm install vue3-image-annotation
Latest Version:1.0.0
Vue:3
License:MIT
Last Updated:Sep 28, 2026
Links: GitHub  ·  npm
Maintainer: jamestoms

vue3-image-annotation

npm version License: MIT test

A Vue 3 image annotation component based on fabric.js — draw rect / circle / polygon annotations on images, with zoom & pan, undo/redo, data echo and PNG export.

基于 fabric.js 的 Vue3 在线图片标注组件。

提供 <ImageCaption /> 组件:缩略图区域 + 主标注区域 + 工具区域,支持矩形、圆形、多边形标注,支持选中拖动、删除、撤销/反撤销、标签管理、标注数据回显与获取。

特性

  • 矩形 / 圆形拖拽绘制,多边形逐点点击绘制(双击或回车结束,ESC 取消)
  • 已标注区域点击选中、按住拖动调整位置(自动限制在图片范围内,松开后重新计算标注坐标)
  • 删除标注(工具栏按钮或 Delete / Backspace 键)
  • 撤销 / 反撤销(Ctrl+Z / Ctrl+Shift+Z / Ctrl+Y,按图片独立记录)
  • 每个标注可关联标签名称,支持自由输入或从预设标签列表选择
  • 鼠标滚轮缩放(以鼠标位置为中心)、左键拖动空白平移、fit 视野
  • 标注坐标基于图片原始像素存储,任何缩放/平移状态下坐标不会错位
  • 屏幕尺寸变化自适应
  • 支持已有标注数据回显、继续编辑
  • 提供 TypeScript 类型声明,同时兼容非 TS 项目
  • 零 UI 框架依赖(按钮/下拉/提示均为自绘实现,不引入 element-plus 等组件库,与宿主项目任何 UI 框架无冲突)

示例截图

demo1 整体界面与标注效果

demo2 标注编辑交互

环境要求

  • Vue ^3.2.0
  • Node >= 18(仅本地开发/构建需要)

fabric 为组件库唯一运行时依赖(dependencies),安装本组件时会自动安装,无需手动处理。

安装

pnpm add vue3-image-annotation
# 或
npm install vue3-image-annotation
# 或
yarn add vue3-image-annotation

使用方式

方式一:全局注册(推荐,vue.use 方式)

// main.ts
import { createApp } from 'vue'
import ImageCaption from 'vue3-image-annotation'
import 'vue3-image-annotation/style.css'
import App from './App.vue'

const app = createApp(App)
app.use(ImageCaption) // 全局注册 <ImageCaption /> 组件
app.mount('#app')
<!-- 任意组件中直接使用 -->
<template>
  <ImageCaption
    :images="images"
    :labels="['行人', '车辆', '建筑']"
    style="height: 640px"
  >
    <!-- 可选:自定义操作区(工具栏右侧),如保存按钮 -->
    <template #actions>
      <button class="ic-btn ic-btn--primary" @click="handleSave">保存</button>
    </template>
  </ImageCaption>
</template>

方式二:按需引入

<script setup lang="ts">
import { ImageCaption } from 'vue3-image-annotation'
import 'vue3-image-annotation/style.css'
</script>

<template>
  <ImageCaption :images="images" />
</template>

非 TypeScript 项目中按普通组件使用即可(组件已编译为 JS,类型声明可选)。

组件 API

Props

名称 类型 必填 默认值 说明
images ImageItem[] 是 [] 图片列表,项内含 annotations 则加载后回显
labels string[] 否 [] 预设标签列表,标签输入时可选择(也可自由输入)
downloadable boolean 否 false 是否开启下载功能(工具栏显示下载按钮,导出含标注的 PNG 图片)

Events

名称 参数 说明
change (imageId: string, annotations: AnnotationData[]) 标注数据发生变化时触发(新增/删除/移动/标签修改/撤销/重做/清空)
download (imageId: string, filename: string) 点击下载按钮导出成功后触发(需开启 downloadable)

插槽

名称 说明
actions 自定义操作区,渲染在工具栏最右侧,适合放置保存/提交/下一步等宿主业务按钮。可直接复用内置按钮样式类 ic-btn(默认)、ic-btn--primary(主要)、ic-btn--danger-plain(危险),也可完全自定义

保存数据最佳实践

组件不内置保存按钮(数据何时、如何持久化由宿主决定),提供两种常用模式:

模式一:实时保存 —— 监听 change 事件,标注每次变化自动提交:

<script setup lang="ts">
import { ref } from 'vue'
import type { AnnotationData } from 'vue3-image-annotation'

const images = ref([
  { id: 'img-1', url: 'https://example.com/a.jpg' },
])

async function handleChange(imageId: string, annotations: AnnotationData[]) {
  await fetch(`/api/annotations/${imageId}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(annotations),
  })
}
</script>

<template>
  <ImageCaption :images="images" @change="handleChange" style="height: 640px" />
</template>

模式二:手动保存 —— 通过 actions 插槽放自己的按钮,点击时从 ref 获取数据(可携带页面其他表单字段一起提交):

<script setup lang="ts">
import { ref } from 'vue'

const captionRef = ref()

async function handleSave() {
  const imageId = captionRef.value.currentImageId
  const annotations = captionRef.value.getAnnotations()
  await fetch(`/api/annotations/${imageId}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(annotations),
  })
}
</script>

<template>
  <ImageCaption ref="captionRef" :images="images" style="height: 640px">
    <template #actions>
      <button class="ic-btn ic-btn--primary" @click="handleSave">保存</button>
    </template>
  </ImageCaption>
</template>

组件方法(通过 ref 调用)

import { ref } from 'vue'

const captionRef = ref()

// 获取当前图片标注数据
captionRef.value.getAnnotations()
// 获取指定图片标注数据
captionRef.value.getAnnotations('img-1')
// 获取全部图片标注数据 { [imageId]: AnnotationData[] }
captionRef.value.getAllAnnotations()
// 撤销 / 反撤销
captionRef.value.undo()
captionRef.value.redo()
// 删除当前选中标注
captionRef.value.deleteSelected()
// 清空当前图片标注
captionRef.value.clearCurrent()
// 视图控制
captionRef.value.zoomIn()
captionRef.value.zoomOut()
captionRef.value.fitView()
// 导出当前图片(含标注)的 PNG dataURL(图片原始像素尺寸,可用于自定义上传等场景)
const dataUrl = captionRef.value.exportImage()
// 当前图片 id(手动保存时配合 getAnnotations 使用)
const imageId = captionRef.value.currentImageId
// 切换图片
captionRef.value.switchImage('img-2')

数据类型

type AnnotationType = 'rect' | 'circle' | 'polygon'

interface Point {
  x: number
  y: number
}

interface AnnotationData {
  id: string
  type: AnnotationType
  label: string
  /** rect / circle:外接框左上角坐标与宽高 */
  x?: number
  y?: number
  width?: number
  height?: number
  /** polygon:顶点列表 */
  points?: Point[]
}

interface ImageItem {
  id: string
  url: string
  name?: string
  /** 已有标注,加载后回显 */
  annotations?: AnnotationData[]
}

所有坐标均为图片原始像素坐标(与画布缩放无关),可直接用于业务存储与换算。

交互说明

操作 行为
鼠标滚轮 以鼠标位置为中心放大 / 缩小
左键拖动空白处 平移图片
点击标注 选中(弹出标签编辑浮层,可改标签、删除)
拖动选中标注 移动位置(限制在图片范围内),松开后自动更新坐标
Delete / Backspace 删除选中标注
Ctrl+Z / Ctrl+Shift+Z(或 Ctrl+Y) 撤销 / 反撤销
清空按钮 首次点击进入红色确认态,3 秒内再次点击执行清空,超时自动还原
ESC 取消绘制 / 取消选中 / 关闭浮层
Enter 结束多边形绘制
双击 / 点击起始顶点 结束多边形绘制

标注对象不支持控制柄缩放(避免坐标换算误差),画错可删除重画或撤销。

本地开发

本项目统一使用 pnpm 作为包管理工具。

# 安装依赖
pnpm install

# 启动 demo 演示页(examples/)
pnpm dev

# 库构建(产物输出至 dist/)
pnpm build

# 类型检查
pnpm typecheck

License

MIT

Related Packages

xiaodao-painter

A Vue 3 component for drawing on the canvas

1,076 0
vue-image-editor

나의 첫 캔버스 이미지 편집기

2,915 5
@nextcloud/image-editor

Vue 3 image editor component for Nextcloud apps

7,319 2
vue-image-annotation

add annotation to the picture

3,696 32
fachwerk

VueJS and Markdown framework for creating interactive learning materials

1,519 0

Version History

Version Released Vue License
1.0.0 ^3.2.0 MIT