kfb-view 2.1.17 → 2.1.20

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kfb-view",
3
3
  "description": "一个在线kfb的阅片软件",
4
- "version": "2.1.17",
4
+ "version": "2.1.20",
5
5
  "author": "qifeng.fan <qifeng.fan@hzztai.com>",
6
6
  "license": "MIT",
7
7
  "main": "lib/kfb-view.js",
@@ -78,7 +78,11 @@ export class Area extends ViewerCommon {
78
78
  this.draging = false;
79
79
  let selectList = [];
80
80
  let selectLabel;
81
+ let prevSelectLabel = undefined;
81
82
  this.labelList.forEach((item) => {
83
+ if (item.select) {
84
+ prevSelectLabel = item;
85
+ }
82
86
  item.select = false;
83
87
  // 如果有可移动的点了,不做操作
84
88
  if (this.movePoint) {
@@ -202,13 +206,15 @@ export class Area extends ViewerCommon {
202
206
  }
203
207
  selectLabel ?
204
208
  this.$emit(EVENT_SELECT_LABEL, selectLabel) :
205
- !this.movePoint ? this.$emit(EVENT_CANCEL_SELECT_LABEL) : '';
209
+ !this.movePoint && prevSelectLabel ?
210
+ this.$emit(EVENT_CANCEL_SELECT_LABEL, prevSelectLabel) : '';
206
211
  this.change();
207
212
  }
208
213
 
209
214
  onCanvasDblClick({x, y}) {
210
215
  setTimeout(() => {
211
- this.$emit(EVENT_DB_CLICK_LABEL);
216
+ const label = this.labelList.find((item) => item.select);
217
+ this.$emit(EVENT_DB_CLICK_LABEL, label);
212
218
  });
213
219
  }
214
220
 
@@ -428,8 +434,9 @@ export class Area extends ViewerCommon {
428
434
  */
429
435
  onCanvasKey(e) {
430
436
  const {originalEvent} = e;
431
- if (originalEvent.code === 'Escape') {
432
- this.$emit(EVENT_CANCEL_SELECT_LABEL);
437
+ const label = this.labelList.find((item) => item.select);
438
+ if (originalEvent.code === 'Escape' && label) {
439
+ this.$emit(EVENT_CANCEL_SELECT_LABEL, label);
433
440
  this.change();
434
441
  }
435
442
  }
@@ -552,7 +559,7 @@ export class Area extends ViewerCommon {
552
559
  label.points[index].canMove = false;
553
560
  if (index === 0 || (!pointInOtherPoint(lastPoint, point, 30) &&
554
561
  !pointInOtherPoint(movePoints[0], point, 30)) ||
555
- (!label.isClose && index === movePoints.length - 1)) {
562
+ (index === movePoints.length - 1)) {
556
563
  lastPoint = point;
557
564
  point.canMove = true;
558
565
  label.points[index].canMove = true;
@@ -48,6 +48,7 @@ export class Board extends ViewerCommon {
48
48
  * @param {boolean} [options.measure=true] 绘画时显示信息
49
49
  * @param {boolean} [options.clear=true] 是否结束绘画时清空画布
50
50
  * @param {boolean} [options.isClose=true] 是否自动闭合曲线
51
+ * @param {boolean} [options.enableDbClickClose=true] 是否双击结束曲线绘制
51
52
  * @param {boolean} [options.once=false] 是否绘画一次后自动结束
52
53
  * @param {boolean} [options.isROI=false] 是否是感性区域
53
54
  * @param {boolean} [options.move=true] 是否可移动
@@ -74,6 +75,7 @@ export class Board extends ViewerCommon {
74
75
  measure: true,
75
76
  clear: true,
76
77
  isClose: true,
78
+ enableDbClickClose: true,
77
79
  ...options,
78
80
  lineWidth: !options.lineWidth ?
79
81
  (this.tool === STAR ? 15 :
@@ -103,6 +105,8 @@ export class Board extends ViewerCommon {
103
105
  text: '',
104
106
  measure: true,
105
107
  clear: true,
108
+ isClose: true,
109
+ enableDbClickClose: true,
106
110
  ...options,
107
111
  lineWidth: !options.lineWidth ?
108
112
  (this.tool === STAR ? 15 :
@@ -141,8 +145,12 @@ export class Board extends ViewerCommon {
141
145
  }
142
146
  this.clearCanvas();
143
147
  this[tool].startDraw();
144
- this[tool].draw(this.imageToViewerElementPoints(this.points));
148
+ const points = this.imageToViewerElementPoints(this.points);
149
+ this[tool].draw(points);
145
150
  this[tool].endDraw();
151
+ if (tool === POLYGON) {
152
+ this[tool].drawPoints(points);
153
+ }
146
154
  this.$emit(EVENT_START_PAINTING, this.getPaintOptions());
147
155
  }
148
156
 
@@ -164,13 +172,18 @@ export class Board extends ViewerCommon {
164
172
  this.points = [this.points[0] || point, point];
165
173
  } else if (tool === POLYGON) {
166
174
  this.points.push(point);
175
+ this.setEnablePoints(false);
167
176
  } else if (POINT_TYPES.includes(tool)) {
168
177
  this.points = [point, point];
169
178
  }
170
179
  this.clearCanvas();
171
180
  this[tool].startDraw();
172
- this[tool].draw(this.imageToViewerElementPoints(this.points));
181
+ const points = this.imageToViewerElementPoints(this.points);
182
+ this[tool].draw(points);
173
183
  this[tool].endDraw();
184
+ if (tool === POLYGON) {
185
+ this[tool].drawPoints(points);
186
+ }
174
187
  this.$emit(EVENT_IN_PAINTING, this.getPaintOptions());
175
188
  }
176
189
 
@@ -195,30 +208,60 @@ export class Board extends ViewerCommon {
195
208
  } else if (POINT_TYPES.includes(tool)) {
196
209
  this.points = [point, point];
197
210
  } else if (tool === POLYGON) {
198
- const points = this.imageToViewerElementPoints(this.points);
199
- let firstPoint = points[0];
200
- // 是否是闭合曲线
201
- const isClose = this[this.tool].options.isClose;
202
- if (isClose) {
203
- // 绘制曲线时,点小于5个,或者曲线不是闭合的
204
- if (points.length < 5 || !pointInOtherPoint(firstPoint, {x, y})) {
211
+ const firstPoint = this.imageToViewerElementCoordinates(this.points[0].x,
212
+ this.points[0].y);
213
+ const enableDbClickClose = this[this.tool].options.enableDbClickClose; // 是否启用双击结束绘制
214
+ const isClose = this[this.tool].options.isClose; // 是否自动关闭
215
+ if (enableDbClickClose) {
216
+ if (isClose && pointInOtherPoint(firstPoint, {x, y})) {
217
+ this.setEnablePoints();
218
+ if (this.points.length < 5) {
219
+ return;
220
+ }
221
+ } else {
222
+ return;
223
+ }
224
+ } else {
225
+ this.setEnablePoints();
226
+ // 如果点小于5个,任务标注不符合规范
227
+ if (this.points.length < 5) {
228
+ this.points = [];
229
+ this.clearCanvas();
205
230
  return;
206
231
  }
207
- } else if (points.length < 5) {
232
+ }
233
+ }
234
+ this.$emit(EVENT_END_PAINTING, this.getPaintOptions());
235
+ // 是否只绘制一次
236
+ if (this[this.tool].options.once) {
237
+ this.endDraw();
238
+ } else if (this[this.tool].options.clear) { // 是否结束绘画时清空画布
239
+ this.points = [];
240
+ this.clearCanvas();
241
+ }
242
+ }
243
+
244
+ /**
245
+ * 监听鼠标双击事件
246
+ * @param {Object} e
247
+ * @param {number} e.x
248
+ * @param {number} e.y
249
+ */
250
+ onCanvasDblClick({x, y}) {
251
+ const point = this.viewerElementToImageCoordinates(x, y);
252
+ if (!this.isInROI(point) || this.points.length === 0) {
253
+ this.points = [];
254
+ this.clearCanvas();
255
+ return;
256
+ }
257
+ if (this.tool === POLYGON) {
258
+ this.setEnablePoints();
259
+ // 如果点小于5个,任务标注不符合规范
260
+ if (this.points.length < 5) {
261
+ this.points = [];
262
+ this.clearCanvas();
208
263
  return;
209
264
  }
210
- // 过滤曲线的点,点之间的距离小于10默认为一个点,取第一个
211
- this.points = this.points.filter((p, index) => {
212
- const _p = this.imageToViewerElementCoordinates(p.x, p.y);
213
- if (index === 0) return true;
214
- if (!isClose && index === this.points.length - 1) return true;
215
- if (pointInOtherPoint(firstPoint, _p)) {
216
- return false;
217
- } else {
218
- firstPoint = _p;
219
- return true;
220
- }
221
- });
222
265
  }
223
266
  this.$emit(EVENT_END_PAINTING, this.getPaintOptions());
224
267
  // 是否只绘制一次
@@ -245,12 +288,18 @@ export class Board extends ViewerCommon {
245
288
  }
246
289
  const tool = this.tool;
247
290
  if (tool === POLYGON && this.points.length > 0) {
248
- this.points.pop();
291
+ if (this.points.length > 1) {
292
+ this.points.pop();
293
+ }
249
294
  this.points.push(point);
250
295
  this.clearCanvas();
251
296
  this[tool].startDraw();
252
- this[tool].draw(this.imageToViewerElementPoints(this.points));
297
+ const points = this.imageToViewerElementPoints(this.points);
298
+ this[tool].draw(points);
253
299
  this[tool].endDraw();
300
+ if (tool === POLYGON) {
301
+ this[tool].drawPoints(points);
302
+ }
254
303
  this.$emit(EVENT_IN_PAINTING, this.getPaintOptions());
255
304
  }
256
305
  }
@@ -260,10 +309,46 @@ export class Board extends ViewerCommon {
260
309
  * @param {Object} e
261
310
  */
262
311
  onCanvasKey(e) {
263
- const {originalEvent} = e;
264
- e.preventDefaultAction = true;
265
- if (originalEvent.code === 'Escape') {
266
- this.endDraw();
312
+ if (this.isInDraw) {
313
+ const {originalEvent} = e;
314
+ if (originalEvent.code === 'Escape') {
315
+ this.endDraw();
316
+ }
317
+ if (originalEvent.code === 'Delete' || originalEvent.key ===
318
+ 'Backspace') {
319
+ // 曲线绘制中,按删除键,删除上一个标注点
320
+ if (this.tool === POLYGON && this.points.length > 1) {
321
+ this.points.splice(this.points.length - 2, 1);
322
+ this.change();
323
+ }
324
+ }
325
+ }
326
+ }
327
+
328
+ setEnablePoints(end = true) {
329
+ const points = this.imageToViewerElementPoints(this.points);
330
+ let firstPoint = points[0];
331
+ // 过滤曲线的点,点之间的距离小于10默认为一个点,取第一个
332
+ this.points = this.points.filter((p, index) => {
333
+ const _p = points[index];
334
+ if (index === 0) return true;
335
+ if (index === this.points.length - 1) return true;
336
+ if (pointInOtherPoint(firstPoint, _p, 30)) {
337
+ return false;
338
+ } else {
339
+ firstPoint = _p;
340
+ return true;
341
+ }
342
+ });
343
+ if (end && this.points.length > 1) {
344
+ const lastPoint = this.points[this.points.length - 1];
345
+ const lastTwoPoint = this.points[this.points.length - 2];
346
+ if (pointInOtherPoint(
347
+ this.imageToViewerElementCoordinates(lastPoint.x, lastPoint.y),
348
+ this.imageToViewerElementCoordinates(lastTwoPoint.x, lastTwoPoint.y),
349
+ 30)) {
350
+ this.points.splice(this.points.length - 2, 1);
351
+ }
267
352
  }
268
353
  }
269
354
 
@@ -328,6 +413,9 @@ export class Board extends ViewerCommon {
328
413
  this[this.tool].startDraw();
329
414
  this[this.tool].draw(points);
330
415
  this[this.tool].endDraw();
416
+ if (this.tool === POLYGON) {
417
+ this[this.tool].drawPoints(points);
418
+ }
331
419
  this.$emit(EVENT_IN_PAINTING, this.getPaintOptions());
332
420
  }
333
421
  }
@@ -151,11 +151,12 @@ class Rotation extends ViewerCommon {
151
151
  * @param {Object} e
152
152
  */
153
153
  onCanvasKey(e) {
154
- const {originalEvent} = e;
155
- e.preventDefaultAction = true;
156
- if (originalEvent.code === 'Escape') {
157
- this.viewport.setRotation(0);
158
- this.stopRotation();
154
+ if (this.isInRotation) {
155
+ const {originalEvent} = e;
156
+ if (originalEvent.code === 'Escape') {
157
+ this.viewport.setRotation(0);
158
+ this.stopRotation();
159
+ }
159
160
  }
160
161
  }
161
162
 
@@ -76,11 +76,12 @@ export class Shape extends ViewerCommon {
76
76
  this.labelList.forEach((item) => {
77
77
  if (item.show === false) return;
78
78
  if (!this[item.tool]) return;
79
- const point = this.imageToViewerElementCoordinates(item.points[0].x,
79
+ if (!this.isInCanvas(item.region)) return;
80
+ /* const point = this.imageToViewerElementCoordinates(item.points[0].x,
80
81
  item.points[0].y);
81
82
  if ((point.x > this.canvas.width ||
82
83
  point.y > this.canvas.height ||
83
- point.x < 0 || point.y < 0)) return;
84
+ point.x < 0 || point.y < 0)) return;*/
84
85
  const key = `${item.strokeStyle ?? ''}_${item.lineWidth ??
85
86
  ''}_${item.fillStyle ?? ''}`;
86
87
  const regionKey = `${item.strokeStyle ?? ''}_${item.lineWidth ?? ''}`;
@@ -133,11 +134,12 @@ export class Shape extends ViewerCommon {
133
134
  regionLabelList.forEach((item) => {
134
135
  if (item.show === false) return;
135
136
  if (!this[item.tool]) return;
136
- const point = this.imageToViewerElementCoordinates(item.points[0].x,
137
- item.points[0].y);
138
- if ((point.x > this.canvas.width ||
139
- point.y > this.canvas.height ||
140
- point.x < 0 || point.y < 0)) return;
137
+ if (!this.isInCanvas(item.region)) return;
138
+ /* const point = this.imageToViewerElementCoordinates(item.points[0].x,
139
+ item.points[0].y);
140
+ if ((point.x > this.canvas.width ||
141
+ point.y > this.canvas.height ||
142
+ point.x < 0 || point.y < 0)) return;*/
141
143
  this.combination.setContent(this.canvas, item);
142
144
  this.combination.draw({
143
145
  points: this.imageToViewerElementPoints(item.points),
@@ -219,10 +219,11 @@ export class Tailoring extends ViewerCommon {
219
219
  * @param {Object} e
220
220
  */
221
221
  onCanvasKey(e) {
222
- const {originalEvent} = e;
223
- e.preventDefaultAction = true;
224
- if (originalEvent.code === 'Escape') {
225
- this.stopTailoring();
222
+ if (this.isInTailoring) {
223
+ const {originalEvent} = e;
224
+ if (originalEvent.code === 'Escape') {
225
+ this.stopTailoring();
226
+ }
226
227
  }
227
228
  }
228
229
 
@@ -16,7 +16,8 @@ class Polygon extends Brush {
16
16
  ctx.lineWidth = this.options.lineWidth;
17
17
  ctx.strokeStyle = this.options.strokeStyle;
18
18
  ctx.moveTo(points[0].x, points[0].y);
19
- points.forEach((point) => {
19
+ points.forEach((point, index) => {
20
+ if (index === 0) return;
20
21
  ctx.lineTo(point.x, point.y);
21
22
  });
22
23
  if (this.options.isClose) {
@@ -26,6 +27,15 @@ class Polygon extends Brush {
26
27
  }
27
28
  }
28
29
  }
30
+
31
+ drawPoints(points) {
32
+ points.forEach((point) => {
33
+ this.thumb.draw(point, {
34
+ thumbRadius: this.options.thumbRadius ?? 5,
35
+ strokeStyle: this.options.thumbColor,
36
+ });
37
+ });
38
+ }
29
39
  }
30
40
 
31
41
  export {
package/src/view.js CHANGED
@@ -309,16 +309,21 @@ function initEvent(kv) {
309
309
  const {originalEvent} = e;
310
310
  handlerCacheEvent(originalEvent, kv);
311
311
  handlerLabelEvent(originalEvent, kv);
312
- kv.shape?.onCanvasKey?.(e);
313
312
  kv.area?.onCanvasKey?.(e);
313
+ kv.shape?.onCanvasKey?.(e);
314
314
  kv.board?.onCanvasKey?.(e);
315
315
  kv.tailoring?.onCanvasKey?.(e);
316
316
  kv.rotation?.onCanvasKey?.(e);
317
317
  }, 100));
318
318
 
319
319
  kv.viewer.addHandler('canvas-double-click', (e) => {
320
- kv.area?.onCanvasDblClick?.(e.position);
321
- kv.tailoring?.onCanvasDblClick?.(e.position);
320
+ if (kv.board?.isInDraw) {
321
+ kv.board.onCanvasDblClick(e.position);
322
+ } else if (kv.tailoring?.isInTailoring) {
323
+ kv.tailoring?.onCanvasDblClick?.(e.position);
324
+ } else {
325
+ kv.area?.onCanvasDblClick?.(e.position);
326
+ }
322
327
  });
323
328
 
324
329
  kv.viewer.addHandler('resize', (e) => {
@@ -331,6 +336,43 @@ function initEvent(kv) {
331
336
  kv.board.onCanvasMove(e);
332
337
  }
333
338
  }, true, kv.$el);
339
+
340
+ let isRightDown = false;
341
+ let dragPosition;
342
+
343
+ kv.viewer.canvas.addEventListener('contextmenu', function(event) {
344
+ if (kv.board?.isInDraw) {
345
+ event.preventDefault();
346
+ }
347
+ });
348
+
349
+ kv.viewer.addHandler('canvas-nonprimary-press', function(e) {
350
+ console.log('nonprimary press');
351
+ if (e.button === 2) {
352
+ isRightDown = true;
353
+ }
354
+ dragPosition = e.position.clone();
355
+ });
356
+
357
+ kv.viewer.addHandler('canvas-nonprimary-release', function(e) {
358
+ console.log('nonprimary release');
359
+ if (e.button === 2) {
360
+ isRightDown = false;
361
+ }
362
+ });
363
+
364
+ new openSeadragon.MouseTracker({
365
+ element: kv.viewer.canvas,
366
+ moveHandler: function(event) {
367
+ if (isRightDown && kv.board?.isInDraw) {
368
+ console.log('nonprimary drag');
369
+ let delta = event.position.minus(dragPosition);
370
+ dragPosition = event.position.clone();
371
+ kv.viewer.viewport.panBy(
372
+ kv.viewer.viewport.deltaPointsFromPixels(delta.negate()));
373
+ }
374
+ },
375
+ });
334
376
  }
335
377
 
336
378
  function handlerCacheEvent(e, kv) {