npm.io
1.0.11 • Published yesterday

@zzalai/leafer-multi-roi

Licence
MIT
Version
1.0.11
Deps
7
Size
586 kB
Vulns
0
Weekly
0

LeaferJS Multi ROI 组件

English | 中文

一个基于 Vue3 和 LeaferJS 的多区域选择组件,用于在图片上进行区域标注和编辑。

功能特点

  • 支持图片加载和显示
  • 支持矩形区域的绘制、编辑和删除
  • 支持画布缩放和拖拽
  • 支持可选的键盘热键操作(需显式启用)
  • 支持撤销/重做功能
  • 支持画布信息 JSON 导出和导入
  • 支持 CSS 变量自定义样式
  • 支持多实例独立使用(每个组件实例状态隔离)

安装

使用 npm
npm install @zzalai/leafer-multi-roi
使用 yarn
yarn add @zzalai/leafer-multi-roi
使用 pnpm
pnpm add @zzalai/leafer-multi-roi

使用方法

基础使用
<template>
  <div class="app">
    <RoiEditor
      :imageSource="imageSource"
      :options="editorOptions"
      @roiChange="handleRoiChange"
      @loadStart="handleLoadStart"
      @loadSuccess="handleLoadSuccess"
      @loadError="handleLoadError"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { RoiEditor } from '@zzalai/leafer-multi-roi'
import '@zzalai/leafer-multi-roi/dist/leafer-multi-roi.css'

// 图片源
const imageUrl = ref('https://picsum.photos/1280/1080')
const imageSource = computed(() => ({
  id: 'test-image',
  url: imageUrl.value
}))

// 编辑器选项
const editorOptions = ref({
  regionStyle: {
    fill: 'rgba(100, 149, 237, 0.3)',
    stroke: 'rgba(100, 149, 237, 0.8)',
    strokeWidth: 2
  },
  selectedRegionStyle: {
    fill: 'rgba(100, 149, 237, 0.5)',
    stroke: 'rgba(100, 149, 237, 1)',
    strokeWidth: 2
  },
  maxRegions: 20, // 最大区域数量限制,默认值为20
  maxUndoSteps: 100, // 最大撤销/重做步数限制,默认值为100
  enableHotkeys: true, // 是否启用键盘热键,默认不启用。显式设置为 true 时注册热键
  loadingGradientColors: ['#e8e0ff', '#d8e8ff'], // 加载动画渐变颜色,默认淡紫到淡蓝
  loadingTextColor: '#4a5568' // 加载提示文字颜色,默认深灰色
})

// 处理ROI变化
const handleRoiChange = (data: any) => {
  console.log('ROI changed:', data)
}

// 处理图片加载开始
const handleLoadStart = () => {
  console.log('Image load started')
}

// 处理图片加载成功
const handleLoadSuccess = (info: { url: string; width: number; height: number; id: string }) => {
  console.log('Image load success:', info)
}

// 处理图片加载失败
const handleLoadError = (error: any) => {
  console.error('Image load error:', error)
}
</script>
手动调用方法
<template>
  <div class="app">
    <RoiEditor
      ref="roiEditor"
      :imageSource="imageSource"
    />
    <button @click="reloadImage">重新加载图片</button>
    <button @click="exportCanvas">导出画布</button>
    <input type="file" @change="importCanvas" accept=".json" />
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { RoiEditor } from '@zzalai/leafer-multi-roi'
import '@zzalai/leafer-multi-roi/dist/leafer-multi-roi.css'

const roiEditor = ref<InstanceType<typeof RoiEditor> | null>(null)
const imageUrl = ref('https://picsum.photos/1280/1080')
const imageSource = computed(() => ({
  id: 'test-image',
  url: imageUrl.value
}))

// 重新加载图片
const reloadImage = () => {
  roiEditor.value?.loadImage()
}

// 导出画布
const exportCanvas = () => {
  const json = roiEditor.value?.exportCanvasJSON()
  if (json) {
    const blob = new Blob([json], { type: 'application/json' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = 'canvas.json'
    a.click()
    URL.revokeObjectURL(url)
  }
}

// 导入画布
const importCanvas = async (event: Event) => {
  const target = event.target as HTMLInputElement
  const file = target.files?.[0]
  if (file) {
    const reader = new FileReader()
    reader.onload = async (e) => {
      const jsonString = e.target?.result as string
      if (roiEditor.value) {
        const success = await roiEditor.value.importCanvasJSON(jsonString, { resetZoom: true })
        if (success) {
          alert('画布导入成功!')
        } else {
          alert('画布导入失败。')
        }
      }
    }
    reader.readAsText(file)
  }
  target.value = ''
}
</script>

适用场景

  • 图片标注:在图片上标注感兴趣的区域
  • 目标检测:为目标检测模型生成训练数据
  • 图像分析:标记图像中的特定区域进行分析
  • 医疗影像:在医疗影像上标记病变区域
  • 电商产品:在产品图片上标记不同的部件

热键操作

注意:热键功能默认不启用,需在初始化时通过 options.enableHotkeys: true 显式开启。每个 RoiEditor 组件实例的热键管理相互独立,支持多实例同时使用而不冲突。

热键 功能
V 选择工具
M 框选工具
Ctrl+Z 撤销
Ctrl+Y 重做
Delete 删除选中区域
Ctrl++ 放大
Ctrl+- 缩小
Ctrl+0 重置缩放
Alt 显示/隐藏热键提示
启用热键示例
<RoiEditor
  :imageSource="imageSource"
  :options="{ enableHotkeys: true }"
/>

暴露的方法

  • getROIAnnotations():获取所有 ROI 标注数据
  • getImageInfo():获取图片信息
  • exportCanvasJSON():导出画布信息为 JSON 字符串
  • importCanvasJSON(jsonString, options):从 JSON 字符串导入画布信息
  • loadImage():手动加载图片
  • undo():撤销上一步操作
  • redo():重做上一步操作
  • selectTool():切换到选择工具
  • rectangleTool():切换到矩形绘制工具
  • deleteSelected():删除选中的区域
  • zoomIn():放大画布
  • zoomOut():缩小画布
  • resetZoom():重置缩放比例

CSS 可重置变量

:root {
  /* 颜色变量 */
  --leafer-roi-color-primary: #007aff; /* 主题色 */
  --leafer-roi-color-background: #f5f5f5; /* 背景色 */
  --leafer-roi-color-background-light: #f0f0f0; /* 浅背景色 */
  --leafer-roi-color-white: #fff; /* 白色 */
  --leafer-roi-color-text: #333; /* 文本色 */
  --leafer-roi-color-text-secondary: #666; /* 次要文本色 */
  --leafer-roi-color-text-tertiary: #999999; /* 三级文本色 */
  --leafer-roi-color-border: #ddd; /* 边框色 */
  --leafer-roi-color-border-light: #e0e0e0; /* 浅边框色 */
  --leafer-roi-color-error: #e74c3c; /* 错误色 */
  --leafer-roi-color-button: #3498db; /* 按钮色 */
  --leafer-roi-color-button-hover: #2980b9; /* 按钮悬停色 */

  /* 尺寸变量 */
  --leafer-roi-padding-toolbar: 10px; /* 工具栏内边距 */
  --leafer-roi-padding-tool-button: 8px; /* 工具按钮内边距 */
  --leafer-roi-size-tool-icon: 18px; /* 工具图标尺寸 */
  --leafer-roi-size-zoom-button: 36px; /* 缩放按钮尺寸 */
  --leafer-roi-size-zoom-value: 60px; /* 缩放值显示宽度 */
  --leafer-roi-font-size-hotkey: 10px; /* 热键提示字体大小 */
  --leafer-roi-padding-hotkey: 1px 3px; /* 热键提示内边距 */
  --leafer-roi-padding-error: 20px; /* 错误提示内边距 */
  --leafer-roi-padding-error-button: 8px 16px; /* 错误提示按钮内边距 */

  /* 边框圆角 */
  --leafer-roi-border-radius-tool-button: 4px; /* 工具按钮圆角 */
  --leafer-roi-border-radius-hotkey: 2px; /* 热键提示圆角 */
  --leafer-roi-border-radius-overlay: 8px; /* 遮罩圆角 */
  --leafer-roi-border-radius-zoom: 8px; /* 缩放控制器圆角 */

  /* 阴影 */
  --leafer-roi-shadow-tool-button: 0 2px 4px rgba(0, 0, 0, 0.1); /* 工具按钮阴影 */
  --leafer-roi-shadow-tool-button-active: 0 2px 4px rgba(0, 122, 255, 0.3); /* 工具按钮激活阴影 */
  --leafer-roi-shadow-tool-button-hover: 0 4px 6px rgba(0, 0, 0, 0.1); /* 工具按钮悬停阴影 */
  --leafer-roi-shadow-overlay: 0 4px 12px rgba(0, 0, 0, 0.1); /* 遮罩阴影 */
  --leafer-roi-shadow-zoom: 0 2px 8px rgba(0, 0, 0, 0.15); /* 缩放控制器阴影 */

  /* 动画 */
  --leafer-roi-transition-time: 0.2s; /* 过渡动画时长 */
  --leafer-roi-animation-gradient: 2s; /* 渐变动画时长 */
}

事件

  • roiChange:当 ROI 发生变化时触发
  • loadStart:当图片开始加载时触发
  • loadSuccess:当图片加载成功时触发
  • loadError:当图片加载失败时触发
  • undoStateChange:当撤销状态变化时触发
  • redoStateChange:当重做状态变化时触发
  • max-regions-exceeded:当达到最大区域数量限制时触发,携带 maxRegions 值,父组件可自定义提示方式

浏览器兼容性

  • Chrome 60+
  • Firefox 55+
  • Safari 12+
  • Edge 79+

依赖

  • Vue 3.3.0+
  • LeaferUI 2.1.0+
  • Tinykeys 4.0.0+
  • @zzalai/leafer-undo-redo 1.0.3+

许可证

MIT License

贡献

欢迎提交 Issue 和 Pull Request!

Keywords