# Vue3 图片标注插件 AILabel

Vue3 图片标注插件 AILabel

近期在做一个图片标注的项目,就是展示一张图片,然后在图片上拖拖拽拽绘制一个一个的框框,然后把框框的位置数据保存起来。

插件 AILabel

NPM:https://www.npmjs.com/package/ailabel?activeTab=readme
GitHub:https://github.com/jlifeng/ailabel

在这里插入图片描述

但是有一个问题啊,就是这个 github 上面或者是 npm 上面的链接都是失效的了,文档都找不到,下面贴一个我弄到的文档,起码我发文的时候还是可以查看的,不知道后期还能不能保住!

文档:https://luchuanqi.github.io/AILabel/doc/preview/#1

安装 AILabel 插件

安装插件很简单哈,一行命令完事儿了。

npm i ailabel

静待安装完成就可以了。

使用(关键代码)

AILabel 使用类似于openlayer,也是那种一个一个的图层往上加,下面简单来个案例哈!

1. 获取图片,获取原始图片的宽高

比如我有一张图片,我需要获取这个图片的宽高是多少,因为我必须于原始图片大小一样,不然的话我标注出来的位置就是不准的,因此需要先获取原始图片宽高。

const url = ref("http://192.168.78.17:5173/static/images/1.jpg")  // 图片地址

// 加载图片 获取图片宽高
const loadImage = () => {
  const img = new Image()
  img.src = url.value
  img.onload = () => {
    imageWidth.value = img.width  // 图片宽度
    imageHeight.value = img.height   // 图片高度
  }
}

2. 初始化 AILabel

初始化标注就是使用 AILabel,然后把图片作为图层中添加到 AILabel 中,同时需要在 AILabel 中添加一个标注图层。

// 初始化标注
const initAnno = () => {
  gMap.value = new AILabel.Map('ed-video-mask', {
    center: { x: imageWidth.value / 2, y: imageHeight.value / 2 },  // 设置一下中心点位置
    zoom: imageWidth.value,  // zoom下面单独说,很重要
    mode: 'PAN',   // 设置类型为平移(可以设置绘制矩形、多边形、圆形等等,默认拖拽就行了)
    refreshDelayWhenZooming: true,  // 这些在文档里面看就行
    zoomWhenDrawing: false,
    panWhenDrawing: false,
    withHotKeys: false
  })

  // 图片图层 (用于展示图片)
  gImageLayer.value = new AILabel.Layer.Image('image-layer', {
    src: url.value,  // 图片地址url (比如:https://xxx.com/1.png)
    width: imageWidth.value,  // 图片实际宽度
    height: imageHeight.value,   // 图片实际高度
    crossOrigin: false,
    position: { x: 0, y: 0 }  // 初始位置
  },
    { name: '图片图层' },
    { zIndex: 1 })

  gMap.value.addLayer(gImageLayer.value)  // 图片图层添加到 AILabel

  // 标注图层 (绘制的框框在这个图层上)
  gFeatureLayer.value = new AILabel.Layer.Feature(
    'feature-layer',
    { name: '标注图层' },
    { zIndex: 2 }
  )
  gMap.value.addLayer(gFeatureLayer.value)   // 标注图层添加到 AILabel
}

这样就可以了。

那个 zoom 是啥意思哈,很重要,比如我的图片原始分辨率尺寸是 3000 * 2000,但是我们标注给的可是区域不一定这么大啊,也许只有1000* 500,那么我们直接标注的话可能就有问题,标注出来的框框位置可能和实际照片的位置不匹配,这个zoom就是来解决这个问题的。

这个 zoom 就是图片宽度的实际大小

比如,我的标注可视区域可能只有1000px,但是图片实际宽度是3000px,图片为了在可视区域放得下,会自动把图片缩小,让图片可以在可视区域完整得放下。这时候其实图片是被缩小的,但是我们标注出来的位置和大小就和原尺寸的对应不上了,这时候我们设置 zoom 为 3000,那么就对应上了,所以,zoom 设置为原始图片宽度就可以!切记切记!不然标注出来的位置是错的!!!

3. 修改 AILabel 的模式

上面默认设置了 PAN,就是平移,这个时候是可以拖拽图片位置,滚轮实现图片缩放的。

当需要鼠标拖拽绘制的时候,需要改为其他的模式,修改方式为:

gMap.value.setMode(mode)

其中 mode 的值可以是:RECTCIRCLEPOLYGONPOINTLINE

含义
RECT 矩形
CIRCLE 圆形
POLYGON 多边形
POINT
LINE 线段
PAN 平移

4. 设置拖拽样式

在我们设置了 gMap.value.setMode('RECT') 绘制矩形的时候,我们按下鼠标左键拖拽的时候会有一个默认样式,当然这是可以设置的,设置起来很简单:

gMap.value.setDrawingStyle({
	strokeStyle: '#409EFF',  // 设置边框颜色
  lineWidth: 2,   // 设置边框宽度
  fillStyle: '#409EFF44',   // 设置填充颜色
  fill: true,    // 启用填充
  stroke: true   // 启用边框
})

5. 事件

事件是啥呢,比如,我绘制完会走哪个函数,选中会走那个函数,修改之后会走哪个函数等等。

我们可以写一个函数绑定这些事件。

// 绑定事件
const bindEvents = () => {
  // 绘制完成回调监听
  gMap.value.events.on('drawDone', (type, data) => {
    createAnnotation(type, data)  // 走了一个函数
  })
  // 要素选中回调监听(非PAN模式下双击选中)
  gMap.value.events.on('featureSelected', (feature) => {
    if (feature) { gMap.value.setActiveFeature(feature) }
  })
  // 要素取消选中回调监听(选中后点击其他位置取消选中)
  gMap.value.events.on('featureUnselected', () => {
    gMap.value.setActiveFeature(null)
  })
  // 要素更新回调监听(选中后编辑完成回调)
  gMap.value.events.on('featureUpdated', (feature, shape) => {
    feature.updateShape(shape)
  })
}

我们开启绘制之后,绘制完一松手发现框框没了,因为我们没有绘制上去,所以我们在绘制完成之后的回调里面,获得了绘制的数据,然后把这个数据自己手写一个框框放到图层上面去:

// 添加要素
const createAnnotation = (type, shape) => {
  const id = `${type}_${uuid4()}`  // 随机ID
  let feature = null
  let style = {
    strokeStyle: '#409EFF',  // 设置边框颜色
 		lineWidth: 2,   // 设置边框宽度
    fillStyle: '#409EFF44',   // 设置填充颜色
    fill: true,    // 启用填充
    stroke: true   // 启用边框
  }
  if (type === 'RECT') {   // 绘制矩形
    feature = new AILabel.Feature.Rect(id, shape, null, style)
  } else if (type === 'CIRCLE') {  // 绘制圆形
    feature = new AILabel.Feature.Circle(id, shape, null, style)
  } else if (type === 'POLYGON') {  // 绘制多边形
    feature = new AILabel.Feature.Polygon(id, { points: shape }, null, style)
  } else if (type === 'POINT') {  // 绘制点
    feature = new AILabel.Feature.Point(id, shape, null, style)
  } else if (type === 'LINE') {   // 绘制线
    feature = new AILabel.Feature.Line(id, shape, null, style)
  }
  gFeatureLayer.value.addFeature(feature)
  return feature;
}

然后就可以了。

在这里插入图片描述

posted @ 2025-12-23 15:59  叫我+V  阅读(3)  评论(0)    收藏  举报