kfb-view 2.1.20 → 2.2.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.
- package/.idea/workspace.xml +54 -53
- package/example/index.js +3 -2
- package/lib/kfb-view.js +1 -1
- package/package.json +1 -1
- package/src/components/area/index.js +66 -44
- package/src/components/board/index.js +31 -18
- package/src/components/rotation/index.js +5 -7
- package/src/components/shape/index.js +72 -52
- package/src/components/tailoring/index.js +3 -5
- package/src/const/event.js +3 -0
- package/src/tool/Brush.js +1 -1
- package/src/tool/Combination.js +1 -0
- package/src/tool/Polygon.js +2 -5
- package/src/tool/Thumb.js +2 -2
- package/src/util/calculate.js +26 -3
- package/src/view.js +59 -20
package/package.json
CHANGED
|
@@ -12,9 +12,10 @@ import {
|
|
|
12
12
|
baseNumber, getAngle, getDistance, getPoint,
|
|
13
13
|
getRectPoint,
|
|
14
14
|
isPointInMatrix,
|
|
15
|
-
pointInOtherPoint, isPointInPolygon, pointsToRegion,
|
|
15
|
+
pointInOtherPoint, isPointInPolygon, pointsToRegion, isPointInLine,
|
|
16
16
|
} from '../../util/calculate';
|
|
17
17
|
import {
|
|
18
|
+
EVENT_ADD_POLYGON_POINT,
|
|
18
19
|
EVENT_AREA_MOVE_END,
|
|
19
20
|
EVENT_AREA_MOVE_START, EVENT_AREA_MOVING, EVENT_CANCEL_SELECT_LABEL,
|
|
20
21
|
EVENT_DB_CLICK_LABEL,
|
|
@@ -48,12 +49,19 @@ export class Area extends ViewerCommon {
|
|
|
48
49
|
/**
|
|
49
50
|
* 画点
|
|
50
51
|
* @param {Object} point
|
|
51
|
-
* @param {
|
|
52
|
+
* @param {Boolean=} active 是否是激活状态
|
|
52
53
|
*/
|
|
53
|
-
drawPoint(point,
|
|
54
|
+
drawPoint(point, active) {
|
|
54
55
|
this.thumb.draw(point, {
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
radius: !active ?
|
|
57
|
+
this.options.thumb.radius :
|
|
58
|
+
this.options.thumb.activeRadius,
|
|
59
|
+
strokeStyle: !active ?
|
|
60
|
+
this.options.thumb.color :
|
|
61
|
+
this.options.thumb.activeColor,
|
|
62
|
+
fillStyle: !active ?
|
|
63
|
+
this.options.thumb.bgColor :
|
|
64
|
+
this.options.thumb.activeBgColor,
|
|
57
65
|
});
|
|
58
66
|
}
|
|
59
67
|
|
|
@@ -214,7 +222,31 @@ export class Area extends ViewerCommon {
|
|
|
214
222
|
onCanvasDblClick({x, y}) {
|
|
215
223
|
setTimeout(() => {
|
|
216
224
|
const label = this.labelList.find((item) => item.select);
|
|
217
|
-
|
|
225
|
+
if (label?.tool === POLYGON) {
|
|
226
|
+
const points = this.imageToViewerElementPoints(label.points);
|
|
227
|
+
let index = -1;
|
|
228
|
+
for (let i = 0, l = points.length, j = l - 1; i < l; j = i, i++) {
|
|
229
|
+
const s = points[i];
|
|
230
|
+
const t = points[j];
|
|
231
|
+
if (isPointInLine({x, y}, [s, t])) {
|
|
232
|
+
index = i;
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (index > -1) {
|
|
237
|
+
const p = this.viewerElementToImageCoordinates(x, y);
|
|
238
|
+
label.points.splice(index, 0, {
|
|
239
|
+
...p,
|
|
240
|
+
canMove: true,
|
|
241
|
+
});
|
|
242
|
+
this.$emit(EVENT_ADD_POLYGON_POINT, label);
|
|
243
|
+
this.change();
|
|
244
|
+
} else {
|
|
245
|
+
this.$emit(EVENT_DB_CLICK_LABEL, label);
|
|
246
|
+
}
|
|
247
|
+
} else {
|
|
248
|
+
this.$emit(EVENT_DB_CLICK_LABEL, label);
|
|
249
|
+
}
|
|
218
250
|
});
|
|
219
251
|
}
|
|
220
252
|
|
|
@@ -237,11 +269,12 @@ export class Area extends ViewerCommon {
|
|
|
237
269
|
|
|
238
270
|
/**
|
|
239
271
|
* 监听鼠标拖动事件
|
|
272
|
+
* @param {Object} position
|
|
273
|
+
* @param {number} position.x
|
|
274
|
+
* @param {number} position.y
|
|
240
275
|
* @param {Object} e
|
|
241
|
-
* @param {number} e.x
|
|
242
|
-
* @param {number} e.y
|
|
243
276
|
*/
|
|
244
|
-
onCanvasDrag({x, y}) {
|
|
277
|
+
onCanvasDrag({x, y}, e) {
|
|
245
278
|
if (this.options.drag === false) return;
|
|
246
279
|
if (!this.lastPoint) this.lastPoint = {x, y};
|
|
247
280
|
const label = this.movePoint.label;
|
|
@@ -251,6 +284,7 @@ export class Area extends ViewerCommon {
|
|
|
251
284
|
if (!isMove && !isResize) return;
|
|
252
285
|
if (position === 4 && !isMove) return;
|
|
253
286
|
if (position !== 4 && !isResize) return;
|
|
287
|
+
e.preventDefaultAction = true;
|
|
254
288
|
const scale = this.getImageZoom(true) / label.scale;
|
|
255
289
|
const tool = label.tool;
|
|
256
290
|
const region = label.region;
|
|
@@ -428,54 +462,42 @@ export class Area extends ViewerCommon {
|
|
|
428
462
|
this.lastPoint = {x, y};
|
|
429
463
|
}
|
|
430
464
|
|
|
431
|
-
/**
|
|
432
|
-
* 监听鼠标按钮事件
|
|
433
|
-
* @param {Object} e
|
|
434
|
-
*/
|
|
435
|
-
onCanvasKey(e) {
|
|
436
|
-
const {originalEvent} = e;
|
|
437
|
-
const label = this.labelList.find((item) => item.select);
|
|
438
|
-
if (originalEvent.code === 'Escape' && label) {
|
|
439
|
-
this.$emit(EVENT_CANCEL_SELECT_LABEL, label);
|
|
440
|
-
this.change();
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
|
|
444
465
|
/**
|
|
445
466
|
* 绘制点
|
|
446
467
|
* @param {Object} points
|
|
447
468
|
* @param {string} type
|
|
448
469
|
*/
|
|
449
|
-
|
|
450
|
-
if (this.options.thumb === false) {
|
|
470
|
+
drawThumbPoints(points, type) {
|
|
471
|
+
if (this.options.thumb.show === false) {
|
|
451
472
|
return;
|
|
452
473
|
}
|
|
453
|
-
const
|
|
474
|
+
const position = this.movePoint?.position;
|
|
454
475
|
if (LINE_TYPES.includes(type)) {
|
|
455
|
-
this.drawPoint(points[0],
|
|
476
|
+
this.drawPoint(points[0], position === 1);
|
|
456
477
|
this.drawPoint({
|
|
457
478
|
x: (points[0].x + points[1].x) / 2,
|
|
458
479
|
y: (points[0].y + points[1].y) / 2,
|
|
459
|
-
},
|
|
460
|
-
this.drawPoint(points[1],
|
|
480
|
+
}, position === 4);
|
|
481
|
+
this.drawPoint(points[1], position === 7);
|
|
461
482
|
} else if (REGION_TYPES.includes(type)) {
|
|
462
|
-
getRectPoint(points[0], points[1]).forEach((point) => {
|
|
463
|
-
this.drawPoint(point,
|
|
483
|
+
getRectPoint(points[0], points[1]).forEach((point, i) => {
|
|
484
|
+
this.drawPoint(point, position === i);
|
|
464
485
|
});
|
|
465
486
|
} else if (type === POLYGON) {
|
|
466
|
-
points.forEach((point) => {
|
|
487
|
+
points.forEach((point, i) => {
|
|
467
488
|
if (point.canMove) {
|
|
468
|
-
this.drawPoint(point,
|
|
489
|
+
this.drawPoint(point, position === i);
|
|
469
490
|
}
|
|
470
491
|
});
|
|
471
492
|
} else if (type === FONT || type === DOT) {
|
|
472
|
-
this.drawPoint(points[0],
|
|
493
|
+
this.drawPoint(points[0], position === 4);
|
|
473
494
|
} else if (type === STAR || type === FLAG) {
|
|
474
495
|
getRectPoint(points[0], points[1]).
|
|
475
|
-
|
|
476
|
-
index ===
|
|
477
|
-
|
|
478
|
-
|
|
496
|
+
forEach((point, index) => {
|
|
497
|
+
if (index === 0 || index === 2 || index === 4 ||
|
|
498
|
+
index === 6 || index === 8) {
|
|
499
|
+
this.drawPoint(point, position === index);
|
|
500
|
+
}
|
|
479
501
|
});
|
|
480
502
|
}
|
|
481
503
|
}
|
|
@@ -496,17 +518,17 @@ export class Area extends ViewerCommon {
|
|
|
496
518
|
region.x + region.width, region.y + region.height);
|
|
497
519
|
const scale = this.getImageZoom(true) / label.scale;
|
|
498
520
|
if (!NO_NORMAL_REGION_TYPES.includes(label.tool)) {
|
|
499
|
-
this.
|
|
521
|
+
this.drawThumbPoints([startPoint, endPoint], label.tool);
|
|
500
522
|
} else if (label.tool === FONT) {
|
|
501
523
|
const fontWidth = this.getFontWidth(label.text, label.fontSize);
|
|
502
524
|
const pt = getPoint(startPoint, {
|
|
503
525
|
x: startPoint.x + fontWidth / 2 * scale,
|
|
504
526
|
y: startPoint.y - label.fontSize / 2 * scale + 4,
|
|
505
527
|
}, label.angle);
|
|
506
|
-
this.
|
|
528
|
+
this.drawThumbPoints([pt], label.tool);
|
|
507
529
|
} else if (label.tool === STAR) {
|
|
508
530
|
const dist = label.lineWidth * scale;
|
|
509
|
-
this.
|
|
531
|
+
this.drawThumbPoints([
|
|
510
532
|
{
|
|
511
533
|
x: startPoint.x - dist,
|
|
512
534
|
y: startPoint.y - dist,
|
|
@@ -515,14 +537,14 @@ export class Area extends ViewerCommon {
|
|
|
515
537
|
y: startPoint.y + dist,
|
|
516
538
|
}], label.tool);
|
|
517
539
|
} else if (label.tool === DOT) {
|
|
518
|
-
this.
|
|
540
|
+
this.drawThumbPoints([
|
|
519
541
|
{
|
|
520
542
|
x: startPoint.x,
|
|
521
543
|
y: startPoint.y,
|
|
522
544
|
}], label.tool);
|
|
523
545
|
} else if (label.tool === FLAG) {
|
|
524
546
|
const dist = label.lineWidth * scale;
|
|
525
|
-
this.
|
|
547
|
+
this.drawThumbPoints([
|
|
526
548
|
{
|
|
527
549
|
x: startPoint.x,
|
|
528
550
|
y: startPoint.y - dist,
|
|
@@ -533,10 +555,10 @@ export class Area extends ViewerCommon {
|
|
|
533
555
|
} else if (label.tool === POLYGON) {
|
|
534
556
|
if (this.draging) {
|
|
535
557
|
const points = this.imageToViewerElementPoints(label.points);
|
|
536
|
-
this.
|
|
558
|
+
this.drawThumbPoints(points, label.tool);
|
|
537
559
|
} else {
|
|
538
560
|
const points = this.setPointsMove(label);
|
|
539
|
-
this.
|
|
561
|
+
this.drawThumbPoints(points, label.tool);
|
|
540
562
|
}
|
|
541
563
|
}
|
|
542
564
|
this[label.tool].setContent(this.canvas, {...label});
|
|
@@ -149,7 +149,11 @@ export class Board extends ViewerCommon {
|
|
|
149
149
|
this[tool].draw(points);
|
|
150
150
|
this[tool].endDraw();
|
|
151
151
|
if (tool === POLYGON) {
|
|
152
|
-
this[tool].drawPoints(points
|
|
152
|
+
this[tool].drawPoints(points, {
|
|
153
|
+
radius: this.options.thumb.radius,
|
|
154
|
+
strokeStyle: this.options.thumb.color,
|
|
155
|
+
fillStyle: this.options.thumb.bgColor,
|
|
156
|
+
});
|
|
153
157
|
}
|
|
154
158
|
this.$emit(EVENT_START_PAINTING, this.getPaintOptions());
|
|
155
159
|
}
|
|
@@ -182,7 +186,11 @@ export class Board extends ViewerCommon {
|
|
|
182
186
|
this[tool].draw(points);
|
|
183
187
|
this[tool].endDraw();
|
|
184
188
|
if (tool === POLYGON) {
|
|
185
|
-
this[tool].drawPoints(points
|
|
189
|
+
this[tool].drawPoints(points, {
|
|
190
|
+
radius: this.options.thumb.radius,
|
|
191
|
+
strokeStyle: this.options.thumb.color,
|
|
192
|
+
fillStyle: this.options.thumb.bgColor,
|
|
193
|
+
});
|
|
186
194
|
}
|
|
187
195
|
this.$emit(EVENT_IN_PAINTING, this.getPaintOptions());
|
|
188
196
|
}
|
|
@@ -298,7 +306,11 @@ export class Board extends ViewerCommon {
|
|
|
298
306
|
this[tool].draw(points);
|
|
299
307
|
this[tool].endDraw();
|
|
300
308
|
if (tool === POLYGON) {
|
|
301
|
-
this[tool].drawPoints(points
|
|
309
|
+
this[tool].drawPoints(points, {
|
|
310
|
+
radius: this.options.thumb.radius,
|
|
311
|
+
strokeStyle: this.options.thumb.color,
|
|
312
|
+
fillStyle: this.options.thumb.bgColor,
|
|
313
|
+
});
|
|
302
314
|
}
|
|
303
315
|
this.$emit(EVENT_IN_PAINTING, this.getPaintOptions());
|
|
304
316
|
}
|
|
@@ -309,18 +321,16 @@ export class Board extends ViewerCommon {
|
|
|
309
321
|
* @param {Object} e
|
|
310
322
|
*/
|
|
311
323
|
onCanvasKey(e) {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
this.change();
|
|
323
|
-
}
|
|
324
|
+
const {originalEvent} = e;
|
|
325
|
+
if (originalEvent.key === 'Escape') {
|
|
326
|
+
this.endDraw();
|
|
327
|
+
}
|
|
328
|
+
if (originalEvent.key === 'Delete' || originalEvent.key ===
|
|
329
|
+
'Backspace') {
|
|
330
|
+
// 曲线绘制中,按删除键,删除上一个标注点
|
|
331
|
+
if (this.tool === POLYGON && this.points.length > 1) {
|
|
332
|
+
this.points.splice(this.points.length - 2, 1);
|
|
333
|
+
this.change();
|
|
324
334
|
}
|
|
325
335
|
}
|
|
326
336
|
}
|
|
@@ -345,8 +355,7 @@ export class Board extends ViewerCommon {
|
|
|
345
355
|
const lastTwoPoint = this.points[this.points.length - 2];
|
|
346
356
|
if (pointInOtherPoint(
|
|
347
357
|
this.imageToViewerElementCoordinates(lastPoint.x, lastPoint.y),
|
|
348
|
-
this.imageToViewerElementCoordinates(lastTwoPoint.x, lastTwoPoint.y)
|
|
349
|
-
30)) {
|
|
358
|
+
this.imageToViewerElementCoordinates(lastTwoPoint.x, lastTwoPoint.y))) {
|
|
350
359
|
this.points.splice(this.points.length - 2, 1);
|
|
351
360
|
}
|
|
352
361
|
}
|
|
@@ -414,7 +423,11 @@ export class Board extends ViewerCommon {
|
|
|
414
423
|
this[this.tool].draw(points);
|
|
415
424
|
this[this.tool].endDraw();
|
|
416
425
|
if (this.tool === POLYGON) {
|
|
417
|
-
this[this.tool].drawPoints(points
|
|
426
|
+
this[this.tool].drawPoints(points, {
|
|
427
|
+
radius: this.options.thumb.radius,
|
|
428
|
+
strokeStyle: this.options.thumb.color,
|
|
429
|
+
fillStyle: this.options.thumb.bgColor,
|
|
430
|
+
});
|
|
418
431
|
}
|
|
419
432
|
this.$emit(EVENT_IN_PAINTING, this.getPaintOptions());
|
|
420
433
|
}
|
|
@@ -91,7 +91,7 @@ class Rotation extends ViewerCommon {
|
|
|
91
91
|
this.drawPoint({
|
|
92
92
|
x: point.x,
|
|
93
93
|
y: point.y,
|
|
94
|
-
}, {
|
|
94
|
+
}, {radius: 5});
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -151,12 +151,10 @@ class Rotation extends ViewerCommon {
|
|
|
151
151
|
* @param {Object} e
|
|
152
152
|
*/
|
|
153
153
|
onCanvasKey(e) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
this.stopRotation();
|
|
159
|
-
}
|
|
154
|
+
const {originalEvent} = e;
|
|
155
|
+
if (originalEvent.key === 'Escape') {
|
|
156
|
+
this.viewport.setRotation(0);
|
|
157
|
+
this.stopRotation();
|
|
160
158
|
}
|
|
161
159
|
}
|
|
162
160
|
|
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
import {ViewerCommon} from '../common/common';
|
|
6
6
|
import * as Tools from '../../tool';
|
|
7
7
|
import {Combination} from '../../tool/Combination';
|
|
8
|
+
import {EVENT_CANCEL_SELECT_LABEL} from '../../const/event';
|
|
9
|
+
import * as EVENTS from '../../const/event';
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* 用来显示标注线的canvas
|
|
@@ -25,6 +27,7 @@ export class Shape extends ViewerCommon {
|
|
|
25
27
|
this[mark] = new Tools[mark];
|
|
26
28
|
});
|
|
27
29
|
this.combination = new Combination();
|
|
30
|
+
this.delaytimer = [];
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
/**
|
|
@@ -32,15 +35,6 @@ export class Shape extends ViewerCommon {
|
|
|
32
35
|
* @param {Object} e
|
|
33
36
|
*/
|
|
34
37
|
onCanvasKey(e) {
|
|
35
|
-
const {originalEvent} = e;
|
|
36
|
-
e.preventDefaultAction = true;
|
|
37
|
-
if (originalEvent.code === 'Escape') {
|
|
38
|
-
this.labelList.forEach((item) => {
|
|
39
|
-
item.select = false;
|
|
40
|
-
item.show = true;
|
|
41
|
-
});
|
|
42
|
-
this.change();
|
|
43
|
-
}
|
|
44
38
|
}
|
|
45
39
|
|
|
46
40
|
/**
|
|
@@ -59,29 +53,24 @@ export class Shape extends ViewerCommon {
|
|
|
59
53
|
this.clearCanvas();
|
|
60
54
|
// 区域标注列表
|
|
61
55
|
const regionLabelList = [];
|
|
62
|
-
this.labelList.
|
|
63
|
-
(item)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
56
|
+
const labelList = this.labelList.filter((item) => {
|
|
57
|
+
if (item.show === false) return false;
|
|
58
|
+
if (!this[item.tool]) return false;
|
|
59
|
+
if (!this.isInCanvas(item.region)) return false;
|
|
60
|
+
if (REGION_TYPES.includes(item.tool) || item.isClose && item.tool ===
|
|
61
|
+
POLYGON && item.fillStyle) {
|
|
62
|
+
regionLabelList.push({
|
|
63
|
+
...item,
|
|
64
|
+
child: [],
|
|
65
|
+
self: item,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
});
|
|
73
70
|
// strokeStyle, lineWidth, fillStyle 相同认为是一个路径下的图形,一起绘制,优化性能
|
|
74
71
|
const sameFixWidthLabel = {}; // star, flag, star, font lineWidth固定为2
|
|
75
72
|
const sameNormalLabel = {};
|
|
76
|
-
|
|
77
|
-
if (item.show === false) return;
|
|
78
|
-
if (!this[item.tool]) return;
|
|
79
|
-
if (!this.isInCanvas(item.region)) return;
|
|
80
|
-
/* const point = this.imageToViewerElementCoordinates(item.points[0].x,
|
|
81
|
-
item.points[0].y);
|
|
82
|
-
if ((point.x > this.canvas.width ||
|
|
83
|
-
point.y > this.canvas.height ||
|
|
84
|
-
point.x < 0 || point.y < 0)) return;*/
|
|
73
|
+
labelList.forEach((item) => {
|
|
85
74
|
const key = `${item.strokeStyle ?? ''}_${item.lineWidth ??
|
|
86
75
|
''}_${item.fillStyle ?? ''}`;
|
|
87
76
|
const regionKey = `${item.strokeStyle ?? ''}_${item.lineWidth ?? ''}`;
|
|
@@ -106,11 +95,41 @@ export class Shape extends ViewerCommon {
|
|
|
106
95
|
parent.child.push(item);
|
|
107
96
|
}
|
|
108
97
|
});
|
|
98
|
+
if (this.delaytimer) {
|
|
99
|
+
clearTimeout(this.delaytimer);
|
|
100
|
+
this.delaytimer = undefined;
|
|
101
|
+
}
|
|
102
|
+
this.deepDrawLabel(sameFixWidthLabel, sameNormalLabel, 1);
|
|
103
|
+
regionLabelList.forEach((item) => {
|
|
104
|
+
this.combination.setContent(this.canvas, item);
|
|
105
|
+
this.combination.draw({
|
|
106
|
+
points: this.imageToViewerElementPoints(item.points),
|
|
107
|
+
tool: item.tool,
|
|
108
|
+
}, item.child.map(({points, tool}) => ({
|
|
109
|
+
points: this.imageToViewerElementPoints(points),
|
|
110
|
+
tool,
|
|
111
|
+
})), this.viewport.getRotation());
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
deepDrawLabel(sameFixWidthLabel, sameNormalLabel, count) {
|
|
116
|
+
let currentDrawCount = 0; // 当前已绘制数量
|
|
109
117
|
const ctx = this.canvas.getContext('2d');
|
|
110
|
-
|
|
118
|
+
const remainFixLabel = {};
|
|
119
|
+
Object.keys(sameFixWidthLabel).forEach((key) => {
|
|
120
|
+
const labels = sameFixWidthLabel[key];
|
|
111
121
|
ctx.beginPath();
|
|
112
122
|
labels.forEach((item) => {
|
|
113
|
-
|
|
123
|
+
if (currentDrawCount >= 5000) { // 一次最多绘制5000个标注,多余标注延迟绘制
|
|
124
|
+
if (remainFixLabel[key]) {
|
|
125
|
+
remainFixLabel[key].push(item);
|
|
126
|
+
} else {
|
|
127
|
+
remainFixLabel[key] = [item];
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
this.drawLabel(item);
|
|
131
|
+
}
|
|
132
|
+
currentDrawCount++;
|
|
114
133
|
});
|
|
115
134
|
const firstLabel = labels?.[0];
|
|
116
135
|
if (firstLabel?.fillStyle) {
|
|
@@ -120,35 +139,36 @@ export class Shape extends ViewerCommon {
|
|
|
120
139
|
ctx.strokeStyle = firstLabel.strokeStyle;
|
|
121
140
|
ctx.stroke();
|
|
122
141
|
});
|
|
123
|
-
|
|
142
|
+
const remainNormalLabel = {};
|
|
143
|
+
Object.keys(sameNormalLabel).forEach((key) => {
|
|
144
|
+
const labels = sameNormalLabel[key];
|
|
124
145
|
ctx.beginPath();
|
|
125
146
|
labels.forEach((item) => {
|
|
126
|
-
|
|
147
|
+
if (currentDrawCount >= 5000) { // 一次最多绘制5000个标注,多余标注延迟绘制
|
|
148
|
+
if (remainNormalLabel[key]) {
|
|
149
|
+
remainNormalLabel[key].push(item);
|
|
150
|
+
} else {
|
|
151
|
+
remainNormalLabel[key] = [item];
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
this.drawLabel(item);
|
|
155
|
+
}
|
|
156
|
+
currentDrawCount++;
|
|
127
157
|
});
|
|
128
158
|
const firstLabel = labels?.[0];
|
|
129
159
|
ctx.lineWidth = firstLabel.lineWidth;
|
|
130
160
|
ctx.strokeStyle = firstLabel.strokeStyle;
|
|
131
161
|
ctx.stroke();
|
|
132
162
|
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
point.x < 0 || point.y < 0)) return;*/
|
|
143
|
-
this.combination.setContent(this.canvas, item);
|
|
144
|
-
this.combination.draw({
|
|
145
|
-
points: this.imageToViewerElementPoints(item.points),
|
|
146
|
-
tool: item.tool,
|
|
147
|
-
}, item.child.map(({points, tool}) => ({
|
|
148
|
-
points: this.imageToViewerElementPoints(points),
|
|
149
|
-
tool,
|
|
150
|
-
})), this.viewport.getRotation());
|
|
151
|
-
});
|
|
163
|
+
if (Object.keys(remainFixLabel).length === 0 &&
|
|
164
|
+
Object.keys(remainNormalLabel).length === 0) {
|
|
165
|
+
console.log(`end deep draw label, draw count: ${count}`);
|
|
166
|
+
this.delaytimer = undefined;
|
|
167
|
+
} else {
|
|
168
|
+
this.delaytimer = setTimeout(() => {
|
|
169
|
+
this.deepDrawLabel(remainFixLabel, remainNormalLabel, count + 1);
|
|
170
|
+
}, 100);
|
|
171
|
+
}
|
|
152
172
|
}
|
|
153
173
|
|
|
154
174
|
drawLabel(item) {
|
|
@@ -219,11 +219,9 @@ export class Tailoring extends ViewerCommon {
|
|
|
219
219
|
* @param {Object} e
|
|
220
220
|
*/
|
|
221
221
|
onCanvasKey(e) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
this.stopTailoring();
|
|
226
|
-
}
|
|
222
|
+
const {originalEvent} = e;
|
|
223
|
+
if (originalEvent.key === 'Escape') {
|
|
224
|
+
this.stopTailoring();
|
|
227
225
|
}
|
|
228
226
|
}
|
|
229
227
|
|
package/src/const/event.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
export const EVENT_START_PAINTING = 'start-painting';
|
|
2
3
|
export const EVENT_IN_PAINTING = 'in-painting';
|
|
3
4
|
export const EVENT_END_PAINTING = 'end-painting';
|
|
@@ -13,4 +14,6 @@ export const EVENT_CACHE_BACK = 'cache-back';
|
|
|
13
14
|
export const EVENT_CACHE_FORWARD = 'cache-forward';
|
|
14
15
|
export const EVENT_HIDDEN_LABEL = 'hidden-label';
|
|
15
16
|
export const EVENT_DELETE_LABEL = 'delete-label';
|
|
17
|
+
export const EVENT_DELETE_POLYGON_POINT = 'delete-polygon-point';
|
|
18
|
+
export const EVENT_ADD_POLYGON_POINT = 'add-polygon-point';
|
|
16
19
|
export const EVENT_NAVIGATOR_VESTIGE = 'navigator-vestige';
|
package/src/tool/Brush.js
CHANGED
package/src/tool/Combination.js
CHANGED
package/src/tool/Polygon.js
CHANGED
|
@@ -28,12 +28,9 @@ class Polygon extends Brush {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
drawPoints(points) {
|
|
31
|
+
drawPoints(points, config) {
|
|
32
32
|
points.forEach((point) => {
|
|
33
|
-
this.
|
|
34
|
-
thumbRadius: this.options.thumbRadius ?? 5,
|
|
35
|
-
strokeStyle: this.options.thumbColor,
|
|
36
|
-
});
|
|
33
|
+
this.drawThumb(point, config);
|
|
37
34
|
});
|
|
38
35
|
}
|
|
39
36
|
}
|
package/src/tool/Thumb.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const ThumbConfig = {
|
|
2
2
|
lineWidth: 2,
|
|
3
|
-
|
|
3
|
+
radius: 5,
|
|
4
4
|
fillStyle: 'rgba(255, 255, 255, 1)',
|
|
5
5
|
strokeStyle: '#01d0b0',
|
|
6
6
|
};
|
|
@@ -51,7 +51,7 @@ class Thumb {
|
|
|
51
51
|
config = this.getConfig(config);
|
|
52
52
|
ctx.beginPath();
|
|
53
53
|
ctx.lineWidth = config.lineWidth;
|
|
54
|
-
ctx.arc(x, y, config.
|
|
54
|
+
ctx.arc(x, y, config.radius, 0, Math.PI * 2, !1);
|
|
55
55
|
ctx.fillStyle = config.fillStyle;
|
|
56
56
|
ctx.fill();
|
|
57
57
|
ctx.strokeStyle = config.strokeStyle;
|
package/src/util/calculate.js
CHANGED
|
@@ -132,9 +132,8 @@ function isPointInPolygon(p, poly) {
|
|
|
132
132
|
if ((sy < py && ty >= py) || (sy >= py && ty < py)) {
|
|
133
133
|
// 线段上与射线 Y 坐标相同的点的 X 坐标
|
|
134
134
|
const x = sx + (py - sy) * (tx - sx) / (ty - sy);
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if (x === px) {
|
|
135
|
+
// 点在多边形的边上,8像素的偏差
|
|
136
|
+
if (Math.abs(x - px) < 10) {
|
|
138
137
|
return true;
|
|
139
138
|
}
|
|
140
139
|
|
|
@@ -149,6 +148,29 @@ function isPointInPolygon(p, poly) {
|
|
|
149
148
|
return flag;
|
|
150
149
|
}
|
|
151
150
|
|
|
151
|
+
/**
|
|
152
|
+
* 判断一个点是否在一条线段上
|
|
153
|
+
* @param {Object} p
|
|
154
|
+
* @param {Object[]} points
|
|
155
|
+
* @return {boolean}
|
|
156
|
+
*/
|
|
157
|
+
function isPointInLine(p, points) {
|
|
158
|
+
const startPoint = points[0];
|
|
159
|
+
const endPoint = points[1];
|
|
160
|
+
// 判断线段两端点是否在射线两侧
|
|
161
|
+
if ((startPoint.y < p.y && endPoint.y >= p.y) ||
|
|
162
|
+
(startPoint.y >= p.y && endPoint.y < p.y)) {
|
|
163
|
+
// 线段上与射线 Y 坐标相同的点的 X 坐标
|
|
164
|
+
const x = startPoint.x + (p.y - startPoint.y) *
|
|
165
|
+
(endPoint.x - startPoint.x) / (endPoint.y - startPoint.y);
|
|
166
|
+
// 点在多边形的边上,8像素的偏差
|
|
167
|
+
if (Math.abs(x - p.x) < 8) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
|
|
152
174
|
/**
|
|
153
175
|
* points转换成Region
|
|
154
176
|
* @param {Object[]} points - 绘制的点
|
|
@@ -366,6 +388,7 @@ export {
|
|
|
366
388
|
pointsToRegion,
|
|
367
389
|
regionToPoint,
|
|
368
390
|
isPointInPolygon,
|
|
391
|
+
isPointInLine,
|
|
369
392
|
isNegNumber,
|
|
370
393
|
baseNumber,
|
|
371
394
|
acreage,
|