Vue3 图片标注插件 AILabel
近期在做一个图片标注的项目,就是展示一张图片,然后在图片上拖拖拽拽绘制一个一个的框框,然后把框框的位置数据保存起来。
插件 AILabel
NPM:www.npmjs.com/package/ail... GitHub:github.com/jlifeng/ail...

但是有一个问题啊,就是这个 github 上面或者是 npm 上面的链接都是失效的了,文档都找不到,下面贴一个我弄到的文档,起码我发文的时候还是可以查看的,不知道后期还能不能保住!
文档:luchuanqi.github.io/AILabel/doc...
安装 AILabel 插件
安装插件很简单哈,一行命令完事儿了。
bash
npm i ailabel
静待安装完成就可以了。
使用(关键代码)
AILabel 使用类似于openlayer,也是那种一个一个的图层往上加,下面简单来个案例哈!
1. 获取图片,获取原始图片的宽高
比如我有一张图片,我需要获取这个图片的宽高是多少,因为我必须于原始图片大小一样,不然的话我标注出来的位置就是不准的,因此需要先获取原始图片宽高。
js
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 中添加一个标注图层。
js
// 初始化标注
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,就是平移,这个时候是可以拖拽图片位置,滚轮实现图片缩放的。
当需要鼠标拖拽绘制的时候,需要改为其他的模式,修改方式为:
javascript
gMap.value.setMode(mode)
其中 mode 的值可以是:RECT、CIRCLE、POLYGON、POINT、LINE。
| 值 | 含义 |
|---|---|
| RECT | 矩形 |
| CIRCLE | 圆形 |
| POLYGON | 多边形 |
| POINT | 点 |
| LINE | 线段 |
| PAN | 平移 |
4. 设置拖拽样式
在我们设置了 gMap.value.setMode('RECT') 绘制矩形的时候,我们按下鼠标左键拖拽的时候会有一个默认样式,当然这是可以设置的,设置起来很简单:
javascript
gMap.value.setDrawingStyle({
strokeStyle: '#409EFF', // 设置边框颜色
lineWidth: 2, // 设置边框宽度
fillStyle: '#409EFF44', // 设置填充颜色
fill: true, // 启用填充
stroke: true // 启用边框
})
5. 事件
事件是啥呢,比如,我绘制完会走哪个函数,选中会走那个函数,修改之后会走哪个函数等等。
我们可以写一个函数绑定这些事件。
javascript
// 绑定事件
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)
})
}
我们开启绘制之后,绘制完一松手发现框框没了,因为我们没有绘制上去,所以我们在绘制完成之后的回调里面,获得了绘制的数据,然后把这个数据自己手写一个框框放到图层上面去:
javascript
// 添加要素
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;
}
然后就可以了。
