luo-image-annotator 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md ADDED
@@ -0,0 +1,36 @@
1
+ # vue-image-annotator
2
+
3
+ #### Description
4
+ 图片标组件
5
+
6
+ #### Software Architecture
7
+ Software architecture description
8
+
9
+ #### Installation
10
+
11
+ 1. xxxx
12
+ 2. xxxx
13
+ 3. xxxx
14
+
15
+ #### Instructions
16
+
17
+ 1. xxxx
18
+ 2. xxxx
19
+ 3. xxxx
20
+
21
+ #### Contribution
22
+
23
+ 1. Fork the repository
24
+ 2. Create Feat_xxx branch
25
+ 3. Commit your code
26
+ 4. Create Pull Request
27
+
28
+
29
+ #### Gitee Feature
30
+
31
+ 1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
32
+ 2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
33
+ 3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
34
+ 4. The most valuable open source project [GVP](https://gitee.com/gvp)
35
+ 5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
36
+ 6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # luo-image-annotator
2
+
3
+ 一个基于 Vue 3 和 Canvas 的图片标注组件库,支持矩形、多边形、关键点、旋转矩形等多种标注类型,并提供批量标注和预览功能。
4
+
5
+ ## 环境要求
6
+
7
+ - **Node.js**: >= 18.0.0
8
+ - **npm**: >= 9.0.0
9
+ - **Vue**: >= 3.2.0
10
+
11
+ ## 开发与运行
12
+
13
+ 如果你想本地开发或查看演示,请按照以下步骤操作:
14
+
15
+ 1. **安装依赖**
16
+
17
+ ```bash
18
+ npm install
19
+ ```
20
+
21
+ 2. **启动开发服务器**
22
+
23
+ ```bash
24
+ npm run dev
25
+ ```
26
+
27
+ 启动后,访问控制台显示的本地地址(通常是 `http://localhost:5173/`)即可查看演示页面。
28
+
29
+ 3. **构建组件库**
30
+
31
+ 如果你需要打包组件库以发布到 npm:
32
+
33
+ ```bash
34
+ npm run build
35
+ ```
36
+
37
+ 构建产物将输出到 `dist` 目录。
38
+
39
+ ## 在其他项目中使用
40
+
41
+ ### 1. 安装
42
+
43
+ 在你的 Vue 3 项目中安装本组件库:
44
+
45
+ ```bash
46
+ npm install luo-image-annotator
47
+ ```
48
+
49
+ 由于本组件库依赖 `element-plus` 和 `@element-plus/icons-vue`,如果你的项目中尚未安装,请同时安装它们:
50
+
51
+ ```bash
52
+ npm install element-plus @element-plus/icons-vue
53
+ ```
54
+
55
+ ### 2. 全局引入 (推荐)
56
+
57
+ 在 `main.ts` 或 `main.js` 中引入样式和组件:
58
+
59
+ ```typescript
60
+ import { createApp } from 'vue'
61
+ import App from './App.vue'
62
+
63
+ // 1. 引入 Element Plus (必选依赖)
64
+ import ElementPlus from 'element-plus'
65
+ import 'element-plus/dist/index.css'
66
+ import * as ElementPlusIconsVue from '@element-plus/icons-vue'
67
+
68
+ // 2. 引入本组件库样式
69
+ import 'luo-image-annotator/dist/style.css'
70
+
71
+ // 3. 引入组件
72
+ import { BatchAnnotator } from 'luo-image-annotator'
73
+
74
+ const app = createApp(App)
75
+
76
+ app.use(ElementPlus)
77
+ // 注册图标
78
+ for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
79
+ app.component(key, component)
80
+ }
81
+
82
+ // 全局注册 BatchAnnotator 组件
83
+ app.component('BatchAnnotator', BatchAnnotator)
84
+
85
+ app.mount('#app')
86
+ ```
87
+
88
+ ### 3. 局部引入
89
+
90
+ 你也可以在单个 `.vue` 文件中局部引入:
91
+
92
+ ```vue
93
+ <template>
94
+ <div style="height: 100vh;">
95
+ <BatchAnnotator
96
+ :images="images"
97
+ :labels="labels"
98
+ @export="handleExport"
99
+ />
100
+ </div>
101
+ </template>
102
+
103
+ <script setup lang="ts">
104
+ import { ref } from 'vue';
105
+ import { BatchAnnotator } from 'luo-image-annotator';
106
+ import 'luo-image-annotator/dist/style.css'; // 别忘了引入样式
107
+
108
+ // 定义标签
109
+ const labels = [
110
+ { id: '1', name: 'Person', color: '#FF0000', visible: true },
111
+ { id: '2', name: 'Car', color: '#00FF00', visible: true }
112
+ ];
113
+
114
+ // 定义图片数据
115
+ const images = ref([
116
+ {
117
+ imageUrl: 'https://example.com/image1.jpg',
118
+ annotations: [] // 初始标注为空
119
+ },
120
+ // ... 更多图片
121
+ ]);
122
+
123
+ // 处理导出事件
124
+ const handleExport = (data) => {
125
+ console.log('导出的标注数据:', data);
126
+ };
127
+ </script>
128
+ ```
129
+
130
+ ## 组件 API
131
+
132
+ ### BatchAnnotator Props
133
+
134
+ | 属性名 | 类型 | 必填 | 描述 |
135
+ | --- | --- | --- | --- |
136
+ | `images` | `Array` | 是 | 图片列表,包含 `imageUrl` 和 `annotations` |
137
+ | `labels` | `Array` | 是 | 标签定义列表,包含 `id`, `name`, `color`, `visible` |
138
+
139
+ ### BatchAnnotator Events
140
+
141
+ | 事件名 | 参数 | 描述 |
142
+ | --- | --- | --- |
143
+ | `export` | `data: Array` | 点击“导出”按钮时触发,返回最新的图片和标注数据 |
144
+ | `update:images` | `data: Array` | 当标注数据发生变化时触发,支持 `v-model:images` |
145
+
146
+ ## 许可证
147
+
148
+ MIT
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1 @@
1
+ .annotation-container[data-v-d3dc5a63]{display:flex;height:100%;width:100%;border:1px solid #e0e0e0;background:#f5f5f5;overflow:hidden}.left-sidebar[data-v-d3dc5a63]{width:50px;background:#fff;border-right:1px solid #e0e0e0;display:flex;flex-direction:column;align-items:center;padding:8px 0;gap:8px;z-index:10}.tool-btn[data-v-d3dc5a63]{width:36px;height:36px;display:flex;align-items:center;justify-content:center;border:1px solid transparent;border-radius:4px;cursor:pointer;-webkit-user-select:none;user-select:none;font-size:18px;transition:all .2s}.tool-btn[data-v-d3dc5a63]:hover{background:#f0f0f0}.tool-btn.active[data-v-d3dc5a63]{background:#e3f2fd;border-color:#2196f3;color:#2196f3}.divider[data-v-d3dc5a63]{width:80%;height:1px;background:#ddd;margin:4px 0}.center-area[data-v-d3dc5a63]{flex:1;display:flex;flex-direction:column;position:relative;overflow:hidden}.top-bar[data-v-d3dc5a63]{height:50px;background:#fff;border-bottom:1px solid #e0e0e0;display:flex;align-items:center;padding:0 16px}.label-selector[data-v-d3dc5a63]{display:flex;align-items:center;gap:12px;width:100%;overflow-x:auto}.label-text[data-v-d3dc5a63]{font-size:14px;font-weight:700;color:#555;white-space:nowrap}.tags-row[data-v-d3dc5a63]{display:flex;gap:8px}.tag-chip[data-v-d3dc5a63]{padding:4px 12px;border-radius:16px;font-size:12px;color:#fff;cursor:pointer;border:2px solid transparent;opacity:.7;transition:all .2s;white-space:nowrap}.tag-chip.active[data-v-d3dc5a63]{opacity:1;transform:scale(1.05);box-shadow:0 2px 4px #0003}.canvas-wrapper[data-v-d3dc5a63]{flex:1;background:#333;position:relative;overflow:hidden}.batch-nav[data-v-d3dc5a63]{height:48px;background:#fff;border-top:1px solid #e0e0e0;display:flex;justify-content:center;align-items:center;gap:16px}.batch-nav button[data-v-d3dc5a63]{padding:6px 16px;background:#f5f5f5;border:1px solid #ddd;border-radius:4px;cursor:pointer}.batch-nav button[data-v-d3dc5a63]:hover:not(:disabled){background:#e0e0e0}.right-sidebar[data-v-d3dc5a63]{width:250px;background:#fff;border-left:1px solid #e0e0e0;display:flex;flex-direction:column;z-index:10}.sidebar-header[data-v-d3dc5a63]{padding:16px;border-bottom:1px solid #eee;display:flex;justify-content:space-between;align-items:center}.sidebar-header h3[data-v-d3dc5a63]{margin:0;font-size:16px}.add-btn[data-v-d3dc5a63]{padding:4px 8px;background:#2196f3;color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:12px}.label-list[data-v-d3dc5a63]{flex:1;overflow-y:auto;padding:8px}.label-item[data-v-d3dc5a63]{margin-bottom:8px;padding:8px;background:#f9f9f9;border-radius:4px;border:1px solid #eee}.label-row[data-v-d3dc5a63]{display:flex;align-items:center;gap:8px}.eye-icon[data-v-d3dc5a63],.delete-icon[data-v-d3dc5a63]{cursor:pointer;font-size:16px;-webkit-user-select:none;user-select:none;opacity:.7}.eye-icon[data-v-d3dc5a63]:hover,.delete-icon[data-v-d3dc5a63]:hover{opacity:1}.color-picker[data-v-d3dc5a63]{width:24px;height:24px;padding:0;border:none;cursor:pointer;background:none}.name-input[data-v-d3dc5a63]{flex:1;border:1px solid transparent;background:transparent;font-size:14px;padding:2px 4px}.name-input[data-v-d3dc5a63]:focus{border-color:#2196f3;background:#fff;outline:none}.color-wrapper[data-v-d3dc5a63]{width:16px;height:16px;border-radius:50%;cursor:pointer;border:1px solid rgba(0,0,0,.1);flex-shrink:0}.label-name[data-v-d3dc5a63]{flex:1;font-size:14px;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.action-icon[data-v-d3dc5a63]{cursor:pointer;font-size:16px;-webkit-user-select:none;user-select:none;width:24px;text-align:center;opacity:.6}.action-icon[data-v-d3dc5a63]:hover{opacity:1}.more-actions[data-v-d3dc5a63]{position:relative;display:flex;justify-content:center;align-items:center}.more-actions .delete-btn[data-v-d3dc5a63]{display:none;font-size:14px}.more-actions:hover .dots[data-v-d3dc5a63]{display:none}.more-actions:hover .delete-btn[data-v-d3dc5a63]{display:inline-block;color:#f44336}.modal-overlay[data-v-d3dc5a63]{position:fixed;top:0;left:0;width:100%;height:100%;background:#00000080;display:flex;justify-content:center;align-items:center;z-index:1000}.modal-content[data-v-d3dc5a63]{background:#fff;padding:20px;border-radius:8px;width:300px;box-shadow:0 4px 12px #00000026}.modal-content h3[data-v-d3dc5a63]{margin:0 0 16px;font-size:18px;color:#333}.form-group[data-v-d3dc5a63]{margin-bottom:16px}.form-group label[data-v-d3dc5a63]{display:block;margin-bottom:8px;font-size:14px;color:#666}.modal-input[data-v-d3dc5a63]{width:100%;padding:8px;border:1px solid #ddd;border-radius:4px;font-size:14px;box-sizing:border-box}.color-input-wrapper[data-v-d3dc5a63]{display:flex;align-items:center;gap:8px}.modal-color-picker[data-v-d3dc5a63]{width:40px;height:30px;padding:0;border:none;background:none;cursor:pointer}.modal-actions[data-v-d3dc5a63]{display:flex;justify-content:flex-end;gap:12px;margin-top:24px}.cancel-btn[data-v-d3dc5a63]{padding:6px 16px;background:#f5f5f5;border:1px solid #ddd;border-radius:4px;cursor:pointer;color:#666}.confirm-btn[data-v-d3dc5a63]{padding:6px 16px;background:#2196f3;border:none;border-radius:4px;cursor:pointer;color:#fff}.cancel-btn[data-v-d3dc5a63]:hover{background:#e0e0e0}.confirm-btn[data-v-d3dc5a63]:hover{background:#1976d2}.thumbnail-wrapper[data-v-78bcbe0c]{position:relative;width:100%;height:100%;overflow:hidden;border-radius:4px;background:#f0f0f0}.thumbnail-image[data-v-78bcbe0c]{width:100%;height:100%;object-fit:cover;display:block}.annotation-overlay[data-v-78bcbe0c]{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.loading-placeholder[data-v-78bcbe0c]{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;color:#999;font-size:12px}.anno-label[data-v-78bcbe0c]{paint-order:stroke;stroke:#fff;stroke-width:2px;stroke-linecap:round;stroke-linejoin:round}.batch-annotator[data-v-4cf50076]{width:100%;height:100vh;display:flex;flex-direction:column;background:#f5f5f5}.gallery-view[data-v-4cf50076]{flex:1;display:flex;flex-direction:column;overflow:hidden;padding:20px;position:relative}.gallery-header[data-v-4cf50076]{margin-bottom:20px;display:flex;justify-content:space-between;align-items:center;flex-shrink:0}.gallery-header h3[data-v-4cf50076]{margin:0;font-size:20px;color:#333}.label-summary[data-v-4cf50076]{display:flex;gap:8px}.label-badge[data-v-4cf50076]{padding:4px 10px;border-radius:12px;color:#fff;font-size:12px;font-weight:700}.gallery-grid[data-v-4cf50076]{flex:1;display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:20px;overflow-y:auto;padding-bottom:80px}.gallery-item[data-v-4cf50076]{background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 8px #0000001a;cursor:pointer;transition:transform .2s,box-shadow .2s;display:flex;flex-direction:column;height:240px}.gallery-item[data-v-4cf50076]:hover{transform:translateY(-4px);box-shadow:0 4px 12px #00000026}.thumbnail-wrapper[data-v-4cf50076]{flex:1;overflow:hidden;position:relative}.img-meta[data-v-4cf50076]{padding:8px;font-size:12px;color:#666;display:flex;justify-content:space-between;background:#fff;border-top:1px solid #eee;height:32px;align-items:center}.bottom-bar[data-v-4cf50076]{position:absolute;bottom:0;left:0;width:100%;height:60px;background:#fff;border-top:1px solid #e0e0e0;display:flex;justify-content:space-between;align-items:center;padding:0 40px;box-shadow:0 -2px 10px #0000000d;z-index:100}.action-btn[data-v-4cf50076]{display:flex;align-items:center;gap:8px;padding:10px 24px;border:none;border-radius:4px;font-size:16px;cursor:pointer;transition:background .2s}.action-btn.primary[data-v-4cf50076]{background:#2196f3;color:#fff}.action-btn.primary[data-v-4cf50076]:hover{background:#1976d2}.action-btn.success[data-v-4cf50076]{background:#4caf50;color:#fff}.action-btn.success[data-v-4cf50076]:hover{background:#388e3c}.editor-view[data-v-4cf50076]{flex:1;display:flex;flex-direction:column;height:100%}.editor-header[data-v-4cf50076]{height:50px;background:#fff;border-bottom:1px solid #e0e0e0;display:flex;align-items:center;padding:0 16px;justify-content:space-between;flex-shrink:0}.header-left[data-v-4cf50076]{display:flex;align-items:center;gap:16px}.back-btn[data-v-4cf50076]{display:flex;align-items:center;gap:4px;background:transparent;border:1px solid #ddd;padding:6px 12px;border-radius:4px;cursor:pointer;font-size:14px;color:#666}.back-btn[data-v-4cf50076]:hover{background:#f5f5f5;color:#333}.editor-content[data-v-4cf50076]{flex:1;overflow:hidden;position:relative}