@zzalai/leafer-point-annotation 1.0.0

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.
@@ -0,0 +1,517 @@
1
+ # 点标注与笔刷涂抹工具 - 需求文档
2
+
3
+ ## 1. 项目概述
4
+
5
+ ### 1.1 项目背景
6
+
7
+ 本项目是一个基于 Vue3 和 LeaferJS 的图像标注工具,主要提供两大核心功能:
8
+ - **点标注**:在图片上添加可编辑的标注点
9
+ - **笔刷涂抹**:在图片上进行涂抹操作并输出二值图
10
+
11
+ ### 1.2 项目目标
12
+
13
+ 为 AI 模型训练提供高质量的标注数据,支持点标注坐标导出和笔刷涂抹区域的二值图输出。
14
+
15
+ ### 1.3 技术栈
16
+
17
+ | 技术 | 版本 | 说明 |
18
+ |------|------|------|
19
+ | Vue | 3.3+ | 前端框架 |
20
+ | TypeScript | 6.0+ | 类型系统 |
21
+ | LeaferUI | 2.0.8+ | Canvas 渲染引擎 |
22
+ | LeaferEditor | 2.0.8+ | 编辑器插件 |
23
+ | LeaferViewport | 2.0.8+ | 视口插件 |
24
+ | LeaferTextEditor | 2.1.0+ | 文本编辑插件 |
25
+ | LeaferResize | 2.0.8+ | 缩放插件 |
26
+ | tinykeys | 3.0+ | 热键系统 |
27
+ | @zzalai/leafer-undo-redo | 1.0.3+ | 撤销/重做系统 |
28
+ | vue-pick-colors | 1.8+ | 颜色选择器 |
29
+
30
+ ---
31
+
32
+ ## 2. 功能需求
33
+
34
+ ### 2.1 点标注功能
35
+
36
+ #### 2.1.1 核心功能
37
+
38
+ | 需求编号 | 功能描述 | 优先级 |
39
+ |----------|----------|--------|
40
+ | P1-001 | 在图片上点击添加标注点 | ⭐⭐⭐ |
41
+ | P1-002 | 标注点由圆点(Ellipse)+ 可编辑标签(Text)组成 | ⭐⭐⭐ |
42
+ | P1-003 | 标注点支持拖拽移动 | ⭐⭐⭐ |
43
+ | P1-004 | 标注点支持删除 | ⭐⭐⭐ |
44
+ | P1-005 | 标签默认值为 #1、#2、#3... 自动递增 | ⭐⭐⭐ |
45
+ | P1-006 | 标签支持编辑,但不允许重复或为空 | ⭐⭐⭐ |
46
+ | P1-007 | 选中状态可通过 app.editor.list 获取 | ⭐⭐⭐ |
47
+ | P1-008 | 支持标注点固定大小(不随画布缩放) | ⭐⭐ |
48
+
49
+ #### 2.1.2 视觉效果
50
+
51
+ | 需求编号 | 功能描述 | 优先级 |
52
+ |----------|----------|--------|
53
+ | P1-101 | Hover 状态:圆点样式变化 | ⭐⭐⭐ |
54
+ | P1-102 | Selected 状态:圆点放大并高亮 | ⭐⭐⭐ |
55
+ | P1-103 | 标签带背景色(boxStyle) | ⭐⭐⭐ |
56
+
57
+ #### 2.1.3 数据输出
58
+
59
+ | 需求编号 | 功能描述 | 优先级 |
60
+ |----------|----------|--------|
61
+ | P1-201 | 输出归一化坐标(0-1) | ⭐⭐⭐ |
62
+ | P1-202 | 输出像素坐标 | ⭐⭐⭐ |
63
+ | P1-203 | 输出标签文本 | ⭐⭐⭐ |
64
+
65
+ ### 2.2 笔刷涂抹功能
66
+
67
+ #### 2.2.1 核心功能
68
+
69
+ | 需求编号 | 功能描述 | 优先级 |
70
+ |----------|----------|--------|
71
+ | P2-001 | 支持笔刷涂抹绘制 | ⭐⭐⭐ |
72
+ | P2-002 | 支持擦除功能 | ⭐⭐⭐ |
73
+ | P2-003 | 实时预览涂抹效果 | ⭐⭐⭐ |
74
+ | P2-004 | 一键清除所有涂抹 | ⭐⭐⭐ |
75
+ | P2-005 | 笔刷大小可调节(通过浮动配置面板) | ⭐⭐⭐ |
76
+ | P2-006 | 笔刷颜色可配置 | ⭐⭐⭐ |
77
+ | P2-007 | 笔刷透明度可配置 | ⭐⭐⭐ |
78
+ | P2-008 | 笔刷连续性阈值可配置 | ⭐⭐ |
79
+ | P2-009 | 使用 Group 控制整体透明度,避免多次叠加 | ⭐⭐ |
80
+ | P2-010 | 提供 hasContent() 方法检测是否有笔刷内容 | ⭐⭐ |
81
+
82
+ #### 2.2.2 输出格式
83
+
84
+ | 需求编号 | 功能描述 | 优先级 |
85
+ |----------|----------|--------|
86
+ | P2-101 | 输出与原图尺寸相同的二值图 | ⭐⭐⭐ |
87
+ | P2-102 | 涂抹区域颜色可配置(默认黑色) | ⭐⭐⭐ |
88
+ | P2-103 | 支持 PNG 和 JPG 格式输出 | ⭐⭐⭐ |
89
+ | P2-104 | JPG 格式自动处理背景色 | ⭐⭐ |
90
+
91
+ ### 2.3 工具切换
92
+
93
+ #### 2.3.1 工具栏
94
+
95
+ | 需求编号 | 功能描述 | 优先级 |
96
+ |----------|----------|--------|
97
+ | P3-001 | 选择工具(热键 V) | ⭐⭐⭐ |
98
+ | P3-002 | 点标注工具(热键 P) | ⭐⭐⭐ |
99
+ | P3-003 | 笔刷工具(热键 B) | ⭐⭐⭐ |
100
+ | P3-004 | 擦除工具(热键 E) | ⭐⭐⭐ |
101
+ | P3-005 | 显示当前激活工具状态 | ⭐⭐⭐ |
102
+ | P3-006 | 点击笔刷工具显示/隐藏配置面板 | ⭐⭐⭐ |
103
+ | P3-007 | 点击面板外其他地方关闭配置面板 | ⭐⭐⭐ |
104
+
105
+ #### 2.3.2 Editor 动态控制
106
+
107
+ | 需求编号 | 功能描述 | 优先级 |
108
+ |----------|----------|--------|
109
+ | P3-101 | 仅在 select 和 point 模式下启用 editor | ⭐⭐⭐ |
110
+ | P3-102 | 笔刷和擦除模式下禁用 editor(避免干扰) | ⭐⭐⭐ |
111
+ | P3-103 | 标签编辑权限控制:仅 select 和 point 工具可编辑 | ⭐⭐⭐ |
112
+ | P3-104 | focusout 时自动取消编辑器选中状态 | ⭐⭐ |
113
+
114
+ ### 2.4 撤销/重做
115
+
116
+ | 需求编号 | 功能描述 | 优先级 |
117
+ |----------|----------|--------|
118
+ | P4-001 | 支持撤销操作(Ctrl+Z) | ⭐⭐⭐ |
119
+ | P4-002 | 支持重做操作(Ctrl+Y) | ⭐⭐⭐ |
120
+ | P4-003 | 点标注和笔刷操作统一管理 | ⭐⭐⭐ |
121
+ | P4-004 | 清除和擦除操作也支持撤销 | ⭐⭐⭐ |
122
+ | P4-005 | 可配置历史记录步数限制(默认100) | ⭐⭐ |
123
+
124
+ ### 2.5 导出/导入
125
+
126
+ #### 2.5.1 导出功能
127
+
128
+ | 需求编号 | 功能描述 | 优先级 |
129
+ |----------|----------|--------|
130
+ | P5-001 | 导出完整画布 JSON 数据(包含笔刷 mask) | ⭐⭐⭐ |
131
+ | P5-002 | 导出 COCO 格式数据 | ⭐⭐ |
132
+ | P5-003 | 导出 YOLO 格式数据 | ⭐⭐ |
133
+ | P5-004 | 导出二值图 Mask(PNG/JPG 可选) | ⭐⭐⭐ |
134
+ | P5-005 | 二值图前景色可配置(黑/白) | ⭐⭐⭐ |
135
+ | P5-006 | 导出格式可通过 options 配置 | ⭐⭐ |
136
+
137
+ #### 2.5.2 导入功能
138
+
139
+ | 需求编号 | 功能描述 | 优先级 |
140
+ |----------|----------|--------|
141
+ | P5-101 | 支持导入 JSON 数据 | ⭐⭐⭐ |
142
+ | P5-102 | 支持重置缩放和自适应图片 | ⭐⭐⭐ |
143
+ | P5-103 | 支持导入不同 URL 的图片 | ⭐⭐ |
144
+
145
+ ### 2.6 画布控制
146
+
147
+ | 需求编号 | 功能描述 | 优先级 |
148
+ |----------|----------|--------|
149
+ | P6-001 | 支持画布缩放(+/-) | ⭐⭐⭐ |
150
+ | P6-002 | 支持重置缩放 | ⭐⭐⭐ |
151
+ | P6-003 | 支持图片自适应画布 | ⭐⭐⭐ |
152
+ | P6-004 | 显示当前缩放比例 | ⭐⭐ |
153
+
154
+ ### 2.7 清除所有功能
155
+
156
+ | 需求编号 | 功能描述 | 优先级 |
157
+ |----------|----------|--------|
158
+ | P7-001 | select 模式下未选中任何点时,按 Delete 清除所有标注和笔刷 | ⭐⭐⭐ |
159
+ | P7-002 | 清除前显示确认对话框 | ⭐⭐⭐ |
160
+
161
+ ---
162
+
163
+ ## 3. 数据结构
164
+
165
+ ### 3.1 点标注数据
166
+
167
+ ```typescript
168
+ interface PointAnnotation {
169
+ id: string; // "point_" + UUID
170
+ pixel: {
171
+ x: number; // 像素坐标 X
172
+ y: number; // 像素坐标 Y
173
+ };
174
+ normalized: {
175
+ x: number; // 归一化坐标 X (0-1)
176
+ y: number; // 归一化坐标 Y (0-1)
177
+ };
178
+ label: string; // 标签文本
179
+ createdAt: number; // 创建时间戳
180
+ updatedAt: number; // 更新时间戳
181
+ }
182
+ ```
183
+
184
+ ### 3.2 笔刷数据(内部快照)
185
+
186
+ ```typescript
187
+ interface BrushSnapshot {
188
+ id: string;
189
+ imageData: string; // Base64 编码的图片数据
190
+ timestamp: number;
191
+ }
192
+ ```
193
+
194
+ ### 3.3 导出数据结构
195
+
196
+ ```typescript
197
+ interface ExportData {
198
+ version: string; // 数据版本
199
+ imageUrl: string; // 图片地址
200
+ imageWidth: number; // 图片宽度
201
+ imageHeight: number; // 图片高度
202
+ pointAnnotations: PointAnnotation[];
203
+ brushMask: string | null; // Base64 编码的笔刷 mask
204
+ exportTime: number; // 导出时间
205
+ }
206
+ ```
207
+
208
+ ### 3.4 COCO 格式数据
209
+
210
+ ```typescript
211
+ interface COCOAnnotation {
212
+ id: number;
213
+ image_id: number;
214
+ category_id: number;
215
+ keypoints: number[]; // [x, y, visibility] 格式
216
+ num_keypoints: number;
217
+ bbox: [number, number, number, number];
218
+ area: number;
219
+ iscrowd: number;
220
+ }
221
+
222
+ interface COCOImage {
223
+ id: number;
224
+ file_name: string;
225
+ width: number;
226
+ height: number;
227
+ }
228
+
229
+ interface COCOCategory {
230
+ id: number;
231
+ name: string;
232
+ keypoints: string[];
233
+ skeleton: number[][];
234
+ }
235
+
236
+ interface COCOExport {
237
+ info: {
238
+ description: string;
239
+ version: string;
240
+ year: number;
241
+ date_created: string;
242
+ };
243
+ licenses: any[];
244
+ images: COCOImage[];
245
+ annotations: COCOAnnotation[];
246
+ categories: COCOCategory[];
247
+ }
248
+ ```
249
+
250
+ ### 3.5 YOLO 格式数据
251
+
252
+ ```typescript
253
+ interface YOLOExport {
254
+ annotations: string; // YOLO 格式的标注字符串
255
+ classNames: string; // 类名列表(每行一个)
256
+ }
257
+ ```
258
+
259
+ ---
260
+
261
+ ## 4. Props 配置
262
+
263
+ ### 4.1 图片源配置
264
+
265
+ | 属性名 | 类型 | 默认值 | 说明 |
266
+ |--------|------|--------|------|
267
+ | imageSource | { id?: string, url: string } | - | 图片源配置 |
268
+
269
+ ### 4.2 点标注样式配置
270
+
271
+ | 属性名 | 类型 | 默认值 | 说明 |
272
+ |--------|------|--------|------|
273
+ | options.pointStyle.circleRadius | number | 12 | 圆点半径 |
274
+ | options.pointStyle.circleFill | string | '#ff4d4f' | 圆点填充色 |
275
+ | options.pointStyle.circleStroke | string | '#ffffff' | 圆点边框色 |
276
+ | options.pointStyle.circleStrokeWidth | number | 2 | 圆点边框宽度 |
277
+ | options.pointStyle.hoverCircleFill | string | '#ff7875' | Hover 填充色 |
278
+ | options.pointStyle.hoverCircleStroke | string | '#ffffff' | Hover 边框色 |
279
+ | options.pointStyle.selectedCircleFill | string | '#1890ff' | Selected 填充色 |
280
+ | options.pointStyle.selectedCircleStroke | string | '#ffffff' | Selected 边框色 |
281
+ | options.pointStyle.selectedCircleScale | number | 1.2 | Selected 放大比例 |
282
+ | options.pointStyle.labelBackgroundColor | string | '#ffffff' | 标签背景色 |
283
+ | options.pointStyle.labelTextColor | string | '#333333' | 标签文字色 |
284
+ | options.pointStyle.labelFontSize | number | 12 | 标签字体大小 |
285
+ | options.pointStyle.labelPadding | number[] | [2, 4] | 标签内边距 |
286
+ | options.pointStyle.fixedSizeOnZoom | boolean | false | 是否开启标注点固定大小(不随画布缩放) |
287
+ | options.pointStyle.fixedSizeScale | number | 1 | 固定大小的缩放系数 |
288
+
289
+ ### 4.3 笔刷样式配置
290
+
291
+ | 属性名 | 类型 | 默认值 | 说明 |
292
+ |--------|------|--------|------|
293
+ | options.brushStyle.color | string | 'rgba(255,0,0,1)' | 笔刷颜色 |
294
+ | options.brushStyle.opacity | number | 0.55 | 透明度 |
295
+ | options.brushStyle.size | number | 100 | 默认笔刷大小 |
296
+ | options.brushStyle.minSize | number | 50 | 最小笔刷大小 |
297
+ | options.brushStyle.maxSize | number | 150 | 最大笔刷大小 |
298
+ | options.brushStyle.continuity | number | 28 | 连续性阈值(像素) |
299
+
300
+ ### 4.4 导出配置
301
+
302
+ | 属性名 | 类型 | 默认值 | 说明 |
303
+ |--------|------|--------|------|
304
+ | options.maskExportFormat | 'png' \| 'jpg' \| 'jpeg' | 'png' | Mask 导出格式 |
305
+ | options.maskExportForeground | 'black' \| 'white' | 'black' | Mask 前景色 |
306
+
307
+ ### 4.5 其他配置
308
+
309
+ | 属性名 | 类型 | 默认值 | 说明 |
310
+ |--------|------|--------|------|
311
+ | options.maxUndoSteps | number | 100 | 最大撤销/重做步数 |
312
+
313
+ ---
314
+
315
+ ## 5. 交互设计
316
+
317
+ ### 5.1 热键映射
318
+
319
+ | 热键 | 功能 | 适用工具 |
320
+ |------|------|----------|
321
+ | V | 选择工具 | 所有 |
322
+ | P | 点标注工具 | 所有 |
323
+ | B | 笔刷工具 | 所有 |
324
+ | E | 擦除工具 | 所有 |
325
+ | Ctrl+Z | 撤销 | 所有 |
326
+ | Ctrl+Y | 重做 | 所有 |
327
+ | Delete | 删除选中/清除所有 | 所有 |
328
+ | Ctrl++ | 放大 | 所有 |
329
+ | Ctrl+- | 缩小 | 所有 |
330
+ | Ctrl+0 | 重置缩放 | 所有 |
331
+ | Alt | 显示/隐藏热键提示 | 所有 |
332
+
333
+ ### 5.2 工具栏交互
334
+
335
+ 1. **工具切换**:点击工具栏按钮切换当前工具,激活状态高亮显示
336
+ 2. **笔刷配置面板**:点击笔刷工具按钮后,在按钮上方浮动显示配置面板
337
+ 3. **浮动面板关闭**:点击空白处或按 ESC 键关闭浮动配置面板
338
+ 4. **热键提示**:按住 Alt 键显示热键提示
339
+
340
+ ### 5.3 点标注交互
341
+
342
+ 1. **创建**:点击画布空白处创建新标注点
343
+ 2. **移动**:拖拽标注点到目标位置
344
+ 3. **编辑标签**:双击标签进入编辑模式,失焦后校验唯一性
345
+ 4. **选择**:点击标注点选中,支持多选(Shift+点击)
346
+ 5. **删除**:选中后按 Delete 键或点击删除按钮
347
+
348
+ ### 5.4 笔刷交互
349
+
350
+ 1. **绘制**:按住鼠标左键拖动进行涂抹
351
+ 2. **擦除**:切换到擦除工具后,按住鼠标左键拖动擦除
352
+ 3. **清除**:点击删除按钮或按 Delete 键清除所有涂抹
353
+ 4. **配置**:点击笔刷工具按钮打开配置面板调整样式
354
+
355
+ ### 5.5 清除所有交互
356
+
357
+ 1. **条件**:select 模式下未选中任何标注点
358
+ 2. **触发**:点击删除按钮或按 Delete 键
359
+ 3. **确认**:显示确认对话框
360
+ 4. **执行**:确认后清除所有标注点和笔刷绘制
361
+
362
+ ---
363
+
364
+ ## 6. 导出格式说明
365
+
366
+ ### 6.1 JSON Full 格式
367
+
368
+ 包含完整的标注数据和笔刷数据,用于数据备份和恢复。
369
+
370
+ ```json
371
+ {
372
+ "version": "1.0",
373
+ "imageUrl": "https://example.com/image.jpg",
374
+ "imageWidth": 1280,
375
+ "imageHeight": 720,
376
+ "pointAnnotations": [
377
+ {
378
+ "id": "point_xxx",
379
+ "pixel": { "x": 100, "y": 200 },
380
+ "normalized": { "x": 0.078, "y": 0.278 },
381
+ "label": "#1",
382
+ "createdAt": 1716960000000,
383
+ "updatedAt": 1716960000000
384
+ }
385
+ ],
386
+ "brushMask": "data:image/png;base64,...",
387
+ "exportTime": 1716960000000
388
+ }
389
+ ```
390
+
391
+ ### 6.2 COCO 格式
392
+
393
+ 符合 COCO 数据集标注格式,用于关键点检测模型训练。
394
+
395
+ ```json
396
+ {
397
+ "info": {
398
+ "description": "Point Annotation Export",
399
+ "version": "1.0",
400
+ "year": 2024,
401
+ "date_created": "2024-05-01"
402
+ },
403
+ "licenses": [],
404
+ "images": [
405
+ {
406
+ "id": 1,
407
+ "file_name": "image.jpg",
408
+ "width": 1280,
409
+ "height": 720
410
+ }
411
+ ],
412
+ "annotations": [
413
+ {
414
+ "id": 1,
415
+ "image_id": 1,
416
+ "category_id": 1,
417
+ "keypoints": [100, 200, 2],
418
+ "num_keypoints": 1,
419
+ "bbox": [92, 192, 24, 24],
420
+ "area": 452.16,
421
+ "iscrowd": 0
422
+ }
423
+ ],
424
+ "categories": [
425
+ {
426
+ "id": 1,
427
+ "name": "point",
428
+ "keypoints": ["point"],
429
+ "skeleton": []
430
+ }
431
+ ]
432
+ }
433
+ ```
434
+
435
+ ### 6.3 YOLO 格式
436
+
437
+ 符合 YOLO 数据集标注格式,包含归一化坐标。
438
+
439
+ ```txt
440
+ # 类名文件(classNames)
441
+ point
442
+
443
+ # 标注文件(annotations)
444
+ 0 0.078 0.278 0.019 0.033
445
+ ```
446
+
447
+ ### 6.4 二值图 Mask 格式
448
+
449
+ PNG 或 JPG 格式图片,涂抹区域为前景色,其余为透明(PNG)或背景色(JPG)。
450
+
451
+ - PNG:涂抹区域为前景色,其余透明
452
+ - JPG:涂抹区域为前景色,其余为背景色(前景为黑则背景为白,反之亦然)
453
+
454
+ ---
455
+
456
+ ## 7. 对外 API
457
+
458
+ ### 7.1 暴露的方法
459
+
460
+ | 方法名 | 参数 | 返回值 | 功能描述 |
461
+ |--------|------|--------|----------|
462
+ | getPointAnnotations | 无 | PointAnnotation[] | 获取所有点标注数据 |
463
+ | getImageInfo | 无 | { id?: string, url: string, width: number, height: number } | 获取图片信息 |
464
+ | exportCanvasJSON | 无 | string | 导出完整 JSON 数据 |
465
+ | exportMaskImage | format?: string, fgColor?: string | Promise<string \| null> | 导出二值图 dataURL |
466
+ | exportCOCO | 无 | string | 导出 COCO 格式 JSON 字符串 |
467
+ | exportYOLO | 无 | { annotations: string, classNames: string } | 导出 YOLO 格式数据 |
468
+ | importCanvasJSON | jsonString: string, options?: { resetZoom?: boolean } | Promise<boolean> | 导入 JSON 数据 |
469
+ | loadImage | url?: string | Promise<void> | 手动加载图片 |
470
+ | clearBrush | 无 | void | 清除所有笔刷内容 |
471
+ | zoomIn | 无 | void | 放大画布 |
472
+ | zoomOut | 无 | void | 缩小画布 |
473
+ | resetZoom | 无 | void | 重置缩放 |
474
+ | undo | 无 | void | 撤销操作 |
475
+ | redo | 无 | void | 重做操作 |
476
+ | getCurrentTool | 无 | 'select' \| 'point' \| 'brush' \| 'eraser' | 获取当前工具 |
477
+ | setTool | tool: string | void | 设置当前工具 |
478
+ | createPointAnnotation | x: number, y: number | string \| null | 创建标注点,返回 id |
479
+ | removePointAnnotation | id: string | boolean | 删除指定 id 的点标注 |
480
+
481
+ ### 7.2 事件
482
+
483
+ | 事件名 | 参数 | 说明 |
484
+ |--------|------|------|
485
+ | pointChange | PointAnnotation[] | 点标注数据变化 |
486
+ | loadStart | - | 图片开始加载 |
487
+ | loadSuccess | - | 图片加载成功 |
488
+ | loadError | error: any | 图片加载失败 |
489
+ | undoStateChange | - | 撤销状态变化 |
490
+ | redoStateChange | - | 重做状态变化 |
491
+
492
+ ---
493
+
494
+ ## 8. 性能要求
495
+
496
+ ### 8.1 响应时间
497
+
498
+ | 操作 | 响应时间要求 |
499
+ |------|--------------|
500
+ | 图片加载 | < 3s |
501
+ | 点标注创建 | < 50ms |
502
+ | 笔刷绘制 | < 16ms(60fps) |
503
+ | 缩放操作 | < 100ms |
504
+ | 撤销/重做 | < 100ms |
505
+
506
+ ### 8.2 浏览器兼容性
507
+
508
+ - Chrome 60+
509
+ - Firefox 55+
510
+ - Safari 12+
511
+ - Edge 79+
512
+
513
+ ---
514
+
515
+ **文档版本**:2.0
516
+ **创建日期**:2024-04-28
517
+ **最后更新**:2024-05-01
@@ -0,0 +1,167 @@
1
+ # 阶段八:测试与优化 - 待完成任务
2
+
3
+ ## 概述
4
+
5
+ 本文档记录了【阶段八:测试与优化】中尚未完成的任务。这些任务主要是对项目整体的完善和优化。
6
+
7
+ ---
8
+
9
+ ## 任务列表
10
+
11
+ ### 8.1 坐标转换测试 ⭐⭐⭐ (P1)
12
+
13
+ #### 任务描述
14
+ 验证点标注的像素坐标与归一化坐标转换的正确性。
15
+
16
+ #### 验收标准
17
+ - [ ] 点标注创建时,pixel 和 normalized 坐标计算正确
18
+ - [ ] 图片缩放后,点标注位置保持正确
19
+ - [ ] 导出数据中坐标值符合预期
20
+ - [ ] 导入数据后点标注位置正确恢复
21
+
22
+ #### 测试用例
23
+ 1. 在图片四个角创建点,验证坐标值
24
+ 2. 在图片中心创建点,验证归一化坐标为 (0.5, 0.5)
25
+ 3. 缩放画布后验证坐标未发生偏移
26
+ 4. 导出再导入,验证坐标一致性
27
+
28
+ ---
29
+
30
+ ### 8.2 标签编辑测试 ⭐⭐⭐ (P1)
31
+
32
+ #### 任务描述
33
+ 全面测试标签编辑功能,包括空值校验、唯一性校验等。
34
+
35
+ #### 验收标准
36
+ - [ ] 双击标签可进入编辑状态
37
+ - [ ] 标签编辑后失焦自动保存
38
+ - [ ] 标签不允许为空(有合理的校验逻辑)
39
+ - [ ] 标签重复时有提示或自动处理
40
+ - [ ] 标签编辑只在 select 和 point 工具可用
41
+
42
+ #### 测试用例
43
+ 1. 创建多个点,编辑标签
44
+ 2. 尝试设置空标签
45
+ 3. 尝试设置重复标签
46
+ 4. 在 brush 模式下尝试编辑标签(应不可编辑)
47
+ 5. 测试 focusout 时编辑器状态
48
+
49
+ ---
50
+
51
+ ### 8.3 撤销/重做完整性测试 ⭐⭐⭐ (P1)
52
+
53
+ #### 任务描述
54
+ 确保所有操作都能正确撤销和重做。
55
+
56
+ #### 验收标准
57
+ - [ ] 点标注创建可以撤销和重做
58
+ - [ ] 点标注删除可以撤销和重做
59
+ - [ ] 点标注移动可以撤销和重做
60
+ - [ ] 笔刷绘制可以撤销和重做
61
+ - [ ] 笔刷擦除可以撤销和重做
62
+ - [ ] 清除所有操作可以撤销和重做
63
+ - [ ] 多次撤销后重做链完整
64
+ - [ ] 历史记录限制生效(超过 100 步自动丢弃最早记录)
65
+
66
+ #### 测试用例
67
+ 1. 创建点 → 撤销 → 点消失 → 重做 → 点恢复
68
+ 2. 删除点 → 撤销 → 点恢复 → 重做 → 点消失
69
+ 3. 连续绘制多笔 → 逐一撤销 → 逐一重做
70
+ 4. 清除所有 → 撤销 → 全部恢复
71
+ 5. 执行 110 步操作 → 验证最早 10 步已不可撤销
72
+
73
+ ---
74
+
75
+ ### 8.4 性能优化 ⭐⭐ (P2)
76
+
77
+ #### 任务描述
78
+ 优化画布渲染性能和高频事件处理。
79
+
80
+ #### 验收标准
81
+ - [ ] 笔刷绘制流畅,无明显卡顿(目标 60fps)
82
+ - [ ] 大量点标注(50+)时缩放流畅
83
+ - [ ] 大尺寸图片(2000x2000+)加载正常
84
+ - [ ] 高频事件处理无内存泄漏
85
+
86
+ #### 优化建议
87
+ 1. 笔刷绘制节流/防抖
88
+ 2. 离屏 Canvas 优化
89
+ 3. 减少不必要的重绘
90
+ 4. 对象池复用
91
+ 5. 事件监听及时清理
92
+
93
+ ---
94
+
95
+ ### 8.5 边界处理 ⭐⭐ (P2)
96
+
97
+ #### 任务描述
98
+ 处理各种边界情况和异常输入。
99
+
100
+ #### 验收标准
101
+ - [ ] 图片加载失败时有友好提示
102
+ - [ ] 网络超时处理
103
+ - [ ] 超大图片适配
104
+ - [ ] 空数据导入不崩溃
105
+ - [ ] 无效格式导入不崩溃
106
+ - [ ] 边界坐标点标注正常
107
+
108
+ #### 测试用例
109
+ 1. 测试无效 URL 图片加载
110
+ 2. 测试断网情况下图片加载
111
+ 3. 测试非常大的图片(如 5000x5000)
112
+ 4. 导入损坏的 JSON 文件
113
+ 5. 在图片边缘创建点标注
114
+
115
+ ---
116
+
117
+ ### 8.6 跨浏览器测试 ⭐ (P3)
118
+
119
+ #### 任务描述
120
+ 在主流浏览器上验证功能正常。
121
+
122
+ #### 验收标准
123
+ - [ ] Chrome 60+ 正常工作
124
+ - [ ] Firefox 55+ 正常工作
125
+ - [ ] Safari 12+ 正常工作
126
+ - [ ] Edge 79+ 正常工作
127
+
128
+ #### 测试重点
129
+ 1. LeaferJS 渲染兼容性
130
+ 2. Canvas API 兼容性
131
+ 3. 热键系统兼容性
132
+ 4. 颜色选择器兼容性
133
+
134
+ ---
135
+
136
+ ### 8.7 文档完善 ⭐⭐ (P2)
137
+
138
+ #### 任务描述
139
+ 完善各种文档,提升用户体验。
140
+
141
+ #### 验收标准
142
+ - [ ] API 文档完整准确
143
+ - [ ] 常见问题 FAQ 文档
144
+ - [ ] 视频教程(可选)
145
+ - [ ] 示例代码丰富
146
+ - [ ] README 文档清晰易懂
147
+
148
+ ---
149
+
150
+ ## 优先级说明
151
+
152
+ - **P1 (⭐⭐⭐)** - 必须完成,影响核心功能
153
+ - **P2 (⭐⭐)** - 建议完成,提升用户体验
154
+ - **P3 (⭐)** - 可选完成,锦上添花
155
+
156
+ ---
157
+
158
+ ## 建议的执行顺序
159
+
160
+ 1. 先完成 P1 任务(8.1, 8.2, 8.3)
161
+ 2. 再完成 P2 任务(8.4, 8.5, 8.7)
162
+ 3. 最后完成 P3 任务(8.6)
163
+
164
+ ---
165
+
166
+ **文档创建日期**:2024-05-01
167
+ **最后更新**:2024-05-01