KLImageAnnotation
考拉图像标注组件
效果
vue
<script setup lang="ts">
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import { useDrawRect } from '../composables/drawRect';
import type { annotation } from '../components/KLImageAnnotation.ts'
const imgSrc = 'img/test.png';
const imgMaskSrc = '';
const width = 5120;
const height = 5120;
const annotations = ref<annotation[]>([
{ title: '类型', content: '图像标注' },
{ title: '时间', content: new Date().toLocaleString() },
])
const rects = ref([
{ id: 1, name: '窗前明月光', position: [400, 3000, 300, 300] },
{ id: 2, name: '疑是地上霜', position: [500, 2800, 420, 320] },
{ id: 3, name: '举头望明月', position: [500, 3000, 380, 500] },
{ id: 4, name: '低头思故乡', position: [1200, 3000, 520, 500] },
])
const imageAnnotation = ref();
const { mousedown, rectPath } = useDrawRect({
getPositionFn(e: MouseEvent) {
return imageAnnotation.value.getPosition(e);
},
rectCallback: () => true,
button: 2,
enable: true,
})
function contextmenu(e: MouseEvent) {
e.preventDefault();
ElMessage.success('右键');
}
function submitEvent() {
}
</script>
<template>
<div class="shadow-block p20" style="height: 600px">
<KLImageAnnotation ref="imageAnnotation" :imgSrc="imgSrc" :imgMaskSrc="imgMaskSrc" :width="width" :height="height"
:annotations="annotations" :rects="rects" :mousedownImageEvent="mousedown" :contextmenuImageEvent="contextmenu" :submitEvent="submitEvent">
<template #image>
<svg :width="width" :height="height" xmlns="http://www.w3.org/2000/svg">
<g stroke="#ff0000" stroke-opacity="1" :stroke-width="4" fill="none">
<path :d="rectPath" />
</g>
</svg>
</template>
<template #rects-detail="{ curSelectIndex, selectByIndex }">
<div class="list-table">
<div class="list-row list-header flex-center">
<div class="row-id">编号</div>
<div class="row-name">详情</div>
</div>
<el-scrollbar height="calc(100% - 34px)">
<div class="list-row flex-center" :class="{ current: curSelectIndex === index }"
v-for="(rect, index) in rects" @click="selectByIndex(index)" :key="index">
<div class="row-id">{{ index + 1 }}</div>
<div class="row-name">{{ rect.name }}</div>
</div>
</el-scrollbar>
</div>
</template>
</KLImageAnnotation>
</div>
</template>类型定义
ts
/** 文字标注信息项 */
export interface annotation {
title: string;
content: string
}
/** 图像标注区域 */
export interface rect {
id: number;
/** [x, y, width, height] */
position: number[];
color?: string;
measureDesc?: string;
}
/** 选中标注项触发源 */
export enum RectChangeEventFrom {
/** 图像区域 */
IMAGE = 'IMAGE',
/** 键盘 */
KEYBOARD = 'KEYBOARD',
/** 列表 */
TABLE = 'TABLE',
}
/** 当前被选中的标注项及其触发源 */
export interface RectChangeEvent {
/** 触发源;接受事件端可根据此字段决定要不要做出反馈,如标注列表滚动到当前标注项 */
from: string | null,
/** 当前被选中的标注项 */
rect: rect | null,
/** 是否静默触发;silent为true时各接受事件端禁止响应rect变化 */
silent: boolean,
}属性
ts
export interface ImageAnnotationProps {
/** 图像地址 */
imgSrc: string;
/** 图像对应掩膜地址 */
imgMaskSrc: string;
/** 图像宽 */
width: number;
/** 图像高 */
height: number;
/** 标注信息列表 */
annotations: annotation[];
/** 标注框列表 */
rects: rect[];
/** 图像标注框列表,默认使用rects */
imgRects?: rect[];
/** 鼠标事件 */
mousedownImageEvent?: (e: MouseEvent) => void;
/** 鼠标右键事件 */
contextmenuImageEvent?: (e: MouseEvent) => void;
/** 点击确认按钮事件 */
submitEvent: () => void;
}slot
| 插槽名 | 说明 | 数据 |
|---|---|---|
| image | 图像区域 | {scale: number} |
| canvas | 画布区域 | - |
| text-detail | 文字解说区域 | - |
| image-detail | 图像地址详细说明区域 | - |
| rects-detail | 标注矩形框列表详情区域 | RectsListProps |
| submit | 确认按钮区域 | - |
typescript
// 标注矩形框列表详情区域传递参数
type RectsListProps = {
// 查看方法selectByRect
selectByRect: (param: RectChangeEvent) => void,
// 查看方法selectByIndex
selectByIndex: (index: number, from: string, silent?: boolean) => void,
// 当前被选中的标注项对应索引
curSelectIndex: number,
// 当前被选中的标注项及其触发源
curRectChange: RectChangeEvent,
}方法
getPosition 获取鼠标相对图像的坐标
typescript
getPosition(e: MouseEvent): coor | nullscrollToRect 图像视野移动到指定区域
typescript
// position [x,y,width,height]
scrollToRect(position: number[]): voidselectByRect 选择指定标注
typescript
selectByRect(param: RectChangeEvent): voidselectByRect 选择指定标注
typescript
selectByIndex(index: number, from: string, silent?: boolean): voidreset 重置画布区域
typescript
reset(): void