@inweb/markup 25.8.2 → 25.8.4

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.
@@ -23,12 +23,22 @@
23
23
 
24
24
  import Konva from "konva";
25
25
  import { IEventEmitter } from "@inweb/eventemitter2";
26
- import { ChangeActiveDraggerEvent, IViewpoint, PanEvent } from "@inweb/viewer-core";
26
+ import {
27
+ ChangeActiveDraggerEvent,
28
+ IArrow,
29
+ ICloud,
30
+ IEllipse,
31
+ IImage,
32
+ ILine,
33
+ IRectangle,
34
+ IText,
35
+ IViewpoint,
36
+ PanEvent,
37
+ } from "@inweb/viewer-core";
27
38
 
28
39
  import { IMarkup, MarkupMode } from "../IMarkup";
29
40
  import { IWorldTransform } from "../IWorldTransform";
30
41
  import { IMarkupObject } from "../IMarkupObject";
31
- import { IMarkupColorable } from "../IMarkupColorable";
32
42
  import { MarkupLineType } from "../IMarkupLine";
33
43
  import { MarkupColor } from "./MarkupColor";
34
44
  import { WorldTransform } from "../WorldTransform";
@@ -85,11 +95,10 @@ const MarkupMode2Konva = {
85
95
  * 2D markup core.
86
96
  */
87
97
  export class KonvaMarkup implements IMarkup {
88
- private _isInitialized = false;
89
98
  private _viewer: IEventEmitter;
90
99
  private _worldTransformer: IWorldTransform;
91
100
  private _container: HTMLElement;
92
- private _pointerEvents: string[];
101
+ private _pointerEvents: string[] = [];
93
102
  private _markupIsActive = false;
94
103
  private _markupMode: MarkupMode;
95
104
  private _markupColor = new MarkupColor(255, 0, 0);
@@ -106,8 +115,6 @@ export class KonvaMarkup implements IMarkup {
106
115
  private _resizeObserver: ResizeObserver;
107
116
  private _zIndex = 1;
108
117
 
109
- private readonly _markupContainerName = "markupContainer";
110
-
111
118
  public lineWidth = 4;
112
119
  public lineType: MarkupLineType = "solid";
113
120
  public fontSize = 34;
@@ -118,10 +125,12 @@ export class KonvaMarkup implements IMarkup {
118
125
  viewer?: IEventEmitter,
119
126
  worldTransformer?: IWorldTransform
120
127
  ): void {
121
- if (!Konva)
122
- throw new Error(
123
- 'Markup: Error during initialization. Konva is not initialized. Update node_modules or add to your page <script src="https://unpkg.com/konva@9/konva.min.js"></script>'
128
+ if (!Konva) {
129
+ console.error(
130
+ 'Markup error: Konva is not initialized. Update node_modules or add to your page <script src="https://unpkg.com/konva@9/konva.min.js"></script>'
124
131
  );
132
+ return;
133
+ }
125
134
 
126
135
  this._viewer = viewer;
127
136
  this._worldTransformer = worldTransformer ?? new WorldTransform();
@@ -129,7 +138,7 @@ export class KonvaMarkup implements IMarkup {
129
138
  this._pointerEvents = pointerEvents ?? [];
130
139
 
131
140
  this._markupContainer = document.createElement("div");
132
- this._markupContainer.id = this._markupContainerName;
141
+ this._markupContainer.id = "markup-container";
133
142
  this._markupContainer.style.position = "absolute";
134
143
  this._markupContainer.style.top = "0px";
135
144
  this._markupContainer.style.left = "0px";
@@ -151,26 +160,21 @@ export class KonvaMarkup implements IMarkup {
151
160
  this._viewer.addEventListener("changeactivedragger", this.changeActiveDragger);
152
161
  this._viewer.addEventListener("pan", this.pan);
153
162
  }
154
-
155
- this._isInitialized = true;
156
163
  }
157
164
 
158
165
  dispose(): void {
159
- if (!this._isInitialized) return;
160
-
161
166
  if (this._viewer) {
162
167
  this._viewer.removeEventListener("pan", this.pan);
163
168
  this._viewer.removeEventListener("changeactivedragger", this.changeActiveDragger);
169
+ this._pointerEvents.forEach((x) => this._markupContainer.removeEventListener(x, this.redirectToViewer));
164
170
  }
165
171
 
166
- this._pointerEvents.forEach((x) => this._markupContainer.removeEventListener(x, this.redirectToViewer));
167
-
168
172
  this.destroyKonva();
169
173
 
170
- this._resizeObserver.disconnect();
174
+ this._resizeObserver?.disconnect();
171
175
  this._resizeObserver = undefined;
172
176
 
173
- this._markupContainer.remove();
177
+ this._markupContainer?.remove();
174
178
  this._markupContainer = undefined;
175
179
 
176
180
  this._container = undefined;
@@ -178,7 +182,6 @@ export class KonvaMarkup implements IMarkup {
178
182
  this._worldTransformer = undefined;
179
183
 
180
184
  this._markupIsActive = false;
181
- this._isInitialized = false;
182
185
  }
183
186
 
184
187
  changeActiveDragger = (event: ChangeActiveDraggerEvent) => {
@@ -201,9 +204,10 @@ export class KonvaMarkup implements IMarkup {
201
204
  const { width, height } = entries[0].contentRect;
202
205
 
203
206
  if (!width || !height) return; // <- invisible container, or container with parent removed
207
+ if (!this._konvaStage) return;
204
208
 
205
- this._konvaStage?.width(width);
206
- this._konvaStage?.height(height);
209
+ this._konvaStage.width(width);
210
+ this._konvaStage.height(height);
207
211
  };
208
212
 
209
213
  pan = (event: PanEvent) => {
@@ -222,7 +226,7 @@ export class KonvaMarkup implements IMarkup {
222
226
  this.removeTextInput();
223
227
  this.removeImageInput();
224
228
  this.clearSelected();
225
- this.getObjects().forEach((obj) => obj.ref().destroy());
229
+ this.getObjects().forEach((obj) => obj.delete());
226
230
  }
227
231
 
228
232
  getMarkupColor(): { r: number; g: number; b: number } {
@@ -235,49 +239,73 @@ export class KonvaMarkup implements IMarkup {
235
239
 
236
240
  colorizeAllMarkup(r: number, g: number, b: number): void {
237
241
  const hexColor = new MarkupColor(r, g, b).HexColor;
238
- this.getObjects().forEach((obj) => {
239
- const colorable = obj as unknown as IMarkupColorable;
240
- if (colorable && colorable.setColor) colorable.setColor(hexColor);
241
- });
242
-
243
- this._konvaLayer.draw();
242
+ this.getObjects().filter((obj: any) => obj.setColor?.(hexColor));
244
243
  }
245
244
 
246
245
  colorizeSelectedMarkups(r: number, g: number, b: number): void {
247
246
  const hexColor = new MarkupColor(r, g, b).HexColor;
248
- this.getSelectedObjects().forEach((obj) => {
249
- const colorable = obj as unknown as IMarkupColorable;
250
- if (colorable && colorable.setColor) colorable.setColor(hexColor);
251
- });
247
+ this.getSelectedObjects().filter((obj: any) => obj.setColor?.(hexColor));
252
248
  }
253
249
 
254
250
  setViewpoint(viewpoint: IViewpoint): void {
255
- const markupColor = viewpoint.custom_fields.markup_color || { r: 255, g: 0, b: 0 };
251
+ const markupColor = viewpoint.custom_fields?.markup_color || { r: 255, g: 0, b: 0 };
256
252
  this.setMarkupColor(markupColor.r, markupColor.g, markupColor.b);
257
253
 
258
- this.loadMarkup(viewpoint);
254
+ viewpoint.lines?.forEach((line: ILine) => {
255
+ const linePoints = [];
256
+ line.points.forEach((point) => {
257
+ const screenPoint = this._worldTransformer.worldToScreen(point);
258
+ linePoints.push(screenPoint.x);
259
+ linePoints.push(screenPoint.y);
260
+ });
261
+ this.addLine(linePoints, line.color, line.type as MarkupLineType, line.width, line.id);
262
+ });
263
+
264
+ viewpoint.texts?.forEach((text: IText) => {
265
+ const screenPoint = this._worldTransformer.worldToScreen(text.position);
266
+ this.addText(text.text, screenPoint, text.angle, text.color, text.text_size, text.font_size, text.id);
267
+ });
268
+
269
+ viewpoint.rectangles?.forEach((rect: IRectangle) => {
270
+ const screenPoint = this._worldTransformer.worldToScreen(rect.position);
271
+ this.addRectangle(screenPoint, rect.width, rect.height, rect.line_width, rect.color, rect.id);
272
+ });
273
+
274
+ viewpoint.ellipses?.forEach((ellipse: IEllipse) => {
275
+ const screenPoint = this._worldTransformer.worldToScreen(ellipse.position);
276
+ this.addEllipse(screenPoint, ellipse.radius, ellipse.line_width, ellipse.color, ellipse.id);
277
+ });
278
+
279
+ viewpoint.arrows?.forEach((arrow: IArrow) => {
280
+ const startPoint = this._worldTransformer.worldToScreen(arrow.start);
281
+ const endPoint = this._worldTransformer.worldToScreen(arrow.end);
282
+ this.addArrow(startPoint, endPoint, arrow.color, arrow.id);
283
+ });
284
+
285
+ viewpoint.clouds?.forEach((cloud: ICloud) => {
286
+ const screenPoint = this._worldTransformer.worldToScreen(cloud.position);
287
+ this.addCloud(screenPoint, cloud.width, cloud.height, cloud.line_width, cloud.color, cloud.id);
288
+ });
289
+
290
+ viewpoint.images?.forEach((image: IImage) => {
291
+ const screenPoint = this._worldTransformer.worldToScreen(image.position);
292
+ this.addImage(screenPoint, image.src, image.width, image.height, image.id);
293
+ });
259
294
  }
260
295
 
261
296
  getViewpoint(): IViewpoint {
262
- const viewpoint: IViewpoint = {
263
- lines: [],
264
- texts: [],
265
- arrows: [],
266
- clouds: [],
267
- ellipses: [],
268
- images: [],
269
- rectangles: [],
270
- };
271
-
272
- viewpoint.snapshot = {
273
- data: this.combineMarkupWithDrawing(),
274
- };
275
-
276
- viewpoint.custom_fields = {
277
- markup_color: this.getMarkupColor(),
278
- };
279
-
280
- this.fillViewpointShapes(viewpoint);
297
+ const viewpoint: IViewpoint = {};
298
+
299
+ viewpoint.lines = this.getMarkupLines();
300
+ viewpoint.texts = this.getMarkupTexts();
301
+ viewpoint.arrows = this.getMarkupArrows();
302
+ viewpoint.clouds = this.getMarkupClouds();
303
+ viewpoint.ellipses = this.getMarkupEllipses();
304
+ viewpoint.images = this.getMarkupImages();
305
+ viewpoint.rectangles = this.getMarkupRectangles();
306
+
307
+ viewpoint.custom_fields = { markup_color: this.getMarkupColor() };
308
+ viewpoint.snapshot = { data: this.combineMarkupWithDrawing() };
281
309
 
282
310
  viewpoint.description = new Date().toDateString();
283
311
  return viewpoint;
@@ -320,6 +348,8 @@ export class KonvaMarkup implements IMarkup {
320
348
  }
321
349
 
322
350
  getSelectedObjects(): IMarkupObject[] {
351
+ if (!this._konvaTransformer) return [];
352
+
323
353
  return this._konvaTransformer
324
354
  .nodes()
325
355
  .map((ref) => {
@@ -331,86 +361,39 @@ export class KonvaMarkup implements IMarkup {
331
361
  }
332
362
 
333
363
  selectObjects(objects: IMarkupObject[]) {
364
+ if (!this._konvaTransformer) return;
365
+
334
366
  const selectedObjs = this._konvaTransformer.nodes().concat(objects.map((x) => x.ref()));
335
367
  this._konvaTransformer.nodes(selectedObjs);
336
368
  }
337
369
 
338
370
  clearSelected(): void {
339
- this._konvaTransformer.nodes([]);
340
- }
341
-
342
- private fillViewpointShapes(viewpoint) {
343
- const markupLines = this.getMarkupLines();
344
- if (markupLines && markupLines.length > 0) {
345
- markupLines?.forEach((line) => {
346
- viewpoint.lines.push(line);
347
- });
348
- }
349
-
350
- const markupTexts = this.getMarkupTexts();
351
- if (markupTexts && markupTexts.length > 0) {
352
- markupTexts?.forEach((text) => {
353
- viewpoint.texts.push(text);
354
- });
355
- }
356
-
357
- const markupRectangles = this.getMarkupRectangles();
358
- if (markupRectangles && markupRectangles.length > 0) {
359
- markupRectangles?.forEach((rectangle) => {
360
- viewpoint.rectangles.push(rectangle);
361
- });
362
- }
363
-
364
- const markupEllipses = this.getMarkupEllipses();
365
- if (markupEllipses && markupEllipses.length > 0) {
366
- markupEllipses?.forEach((ellipse) => {
367
- viewpoint.ellipses.push(ellipse);
368
- });
369
- }
370
-
371
- const markupArrows = this.getMarkupArrows();
372
- if (markupArrows && markupArrows.length > 0) {
373
- markupArrows?.forEach((arrow) => {
374
- viewpoint.arrows.push(arrow);
375
- });
376
- }
377
-
378
- const markupImages = this.getMarkupImages();
379
- if (markupImages && markupImages.length > 0) {
380
- markupImages?.forEach((image) => {
381
- viewpoint.images.push(image);
382
- });
383
- }
384
-
385
- const markupClouds = this.getMarkupClouds();
386
- if (markupClouds && markupClouds.length > 0) {
387
- markupClouds?.forEach((cloud) => {
388
- viewpoint.clouds.push(cloud);
389
- });
390
- }
371
+ if (this._konvaTransformer) this._konvaTransformer.nodes([]);
391
372
  }
392
373
 
393
374
  private addObject(object: IMarkupObject): void {
394
- this._konvaLayer.add(object.ref());
375
+ if (this._konvaLayer) this._konvaLayer.add(object.ref());
395
376
  }
396
377
 
397
378
  private konvaLayerFind(type: string): any {
379
+ if (!this._konvaLayer) return [];
380
+
398
381
  const konvaShape = MarkupMode2Konva[type];
399
- if (konvaShape && konvaShape.initializer) {
400
- // for "draggable" Konva uses Rectangles in Transformer. We need only Shapes from layer.
401
- return this._konvaLayer.find(konvaShape.name).filter((ref) => ref.parent === this._konvaLayer);
402
- }
403
- return [];
382
+ if (!konvaShape || !konvaShape.initializer) return [];
383
+
384
+ // for "draggable" Konva uses Rectangles in Transformer. We need only Shapes from layer.
385
+ return this._konvaLayer.find(konvaShape.name).filter((ref) => ref.parent === this._konvaLayer);
404
386
  }
405
387
 
406
388
  private initializeKonva(): any {
407
389
  // first we need Konva core things: stage and layer
408
- this._konvaStage = new Konva.Stage({
409
- container: this._markupContainerName,
390
+ const stage = new Konva.Stage({
391
+ container: this._markupContainer,
410
392
  width: this._container.clientWidth,
411
393
  height: this._container.clientHeight,
412
394
  });
413
- const stage = this._konvaStage;
395
+ this._konvaStage = stage;
396
+
414
397
  const layer = new Konva.Layer({ pixelRation: window.devicePixelRatio });
415
398
  stage.add(layer);
416
399
  this._konvaLayer = layer;
@@ -420,9 +403,8 @@ export class KonvaMarkup implements IMarkup {
420
403
  keepRatio: false,
421
404
  flipEnabled: false,
422
405
  });
423
-
424
- this._konvaTransformer = transformer;
425
406
  layer.add(transformer);
407
+ this._konvaTransformer = transformer;
426
408
 
427
409
  let isPaint = false;
428
410
  let lastLine;
@@ -618,12 +600,8 @@ export class KonvaMarkup implements IMarkup {
618
600
  container.addEventListener("keydown", (e) => {
619
601
  if (!this._markupIsActive) return;
620
602
  if (e.code === "Delete") {
621
- const trNodes = this._konvaTransformer.nodes();
622
- if (trNodes.length > 0) {
623
- this._konvaTransformer.nodes().forEach((x) => x.destroy());
624
- this._konvaTransformer.nodes([]);
625
- }
626
- layer.draw();
603
+ this.getSelectedObjects().forEach((obj: IMarkupObject) => obj.delete());
604
+ this.clearSelected();
627
605
  return;
628
606
  }
629
607
  e.preventDefault();
@@ -633,20 +611,22 @@ export class KonvaMarkup implements IMarkup {
633
611
  private destroyKonva() {
634
612
  this.clearOverlay();
635
613
 
636
- this._konvaStage.destroy();
614
+ this._konvaStage?.destroy();
637
615
 
638
616
  this._konvaLayer = undefined;
639
617
  this._konvaTransformer = undefined;
640
618
  this._konvaStage = undefined;
641
619
  }
642
620
 
643
- private getMarkupLines() {
621
+ private getMarkupLines(): Array<ILine> {
644
622
  const lines = [];
645
- this.konvaLayerFind("Line").forEach((line) => {
646
- const linePoints = line.points();
623
+
624
+ this.konvaLayerFind("Line").forEach((ref) => {
625
+ const linePoints = ref.points();
647
626
  if (!linePoints) return;
627
+
648
628
  const worldPoints = [];
649
- const absoluteTransform = line.getAbsoluteTransform();
629
+ const absoluteTransform = ref.getAbsoluteTransform();
650
630
  for (let i = 0; i < linePoints.length; i += 2) {
651
631
  // we need getAbsoluteTransform because inside Konva position starts from {0, 0}
652
632
  // https://stackoverflow.com/a/57641487 - check answer's comments
@@ -656,33 +636,33 @@ export class KonvaMarkup implements IMarkup {
656
636
  worldPoints.push(worldPoint);
657
637
  }
658
638
 
659
- const konvaLine = new KonvaLine(null, line);
660
- lines.push({
639
+ const konvaLine = new KonvaLine(null, ref);
640
+ const line: ILine = {
661
641
  id: konvaLine.id(),
662
642
  points: worldPoints,
663
643
  color: konvaLine.getColor() || "#ff0000",
664
644
  type: konvaLine.getLineType() || this.lineType,
665
645
  width: konvaLine.getLineWidth() || this.lineWidth,
666
- });
646
+ };
647
+
648
+ lines.push(line);
667
649
  });
668
650
 
669
651
  return lines;
670
652
  }
671
653
 
672
- private getMarkupTexts() {
654
+ private getMarkupTexts(): Array<IText> {
673
655
  const texts = [];
674
656
 
675
- const textSize = 0.02;
676
- const textScale = this._worldTransformer.getScale();
677
-
678
- this.konvaLayerFind("Text").forEach((text) => {
679
- if (!text) return;
657
+ this.konvaLayerFind("Text").forEach((ref) => {
658
+ const textSize = 0.02;
659
+ const textScale = this._worldTransformer.getScale();
680
660
 
681
- const position = { x: text.x(), y: text.y() };
661
+ const position = { x: ref.x(), y: ref.y() };
682
662
  const worldPoint = this._worldTransformer.screenToWorld(position);
683
663
 
684
- const shape = new KonvaText(null, text);
685
- texts.push({
664
+ const shape = new KonvaText(null, ref);
665
+ const text: IText = {
686
666
  id: shape.id(),
687
667
  position: worldPoint,
688
668
  text: shape.getText(),
@@ -690,168 +670,143 @@ export class KonvaMarkup implements IMarkup {
690
670
  angle: shape.getRotation(),
691
671
  color: shape.getColor(),
692
672
  font_size: shape.getFontSize(),
693
- });
673
+ };
674
+
675
+ texts.push(text);
694
676
  });
695
677
 
696
678
  return texts;
697
679
  }
698
680
 
699
- private getMarkupRectangles() {
681
+ private getMarkupRectangles(): Array<IRectangle> {
700
682
  const rectangles = [];
701
- this.konvaLayerFind("Rectangle").forEach((rect) => {
702
- const position = rect.position();
683
+
684
+ this.konvaLayerFind("Rectangle").forEach((ref) => {
685
+ const position = ref.position();
703
686
  const worldPoint = this._worldTransformer.screenToWorld(position);
704
687
 
705
- const shape = new KonvaRectangle(null, rect);
706
- rectangles.push({
688
+ const shape = new KonvaRectangle(null, ref);
689
+ const rectangle: IRectangle = {
707
690
  id: shape.id(),
708
691
  position: worldPoint,
709
692
  width: shape.getWidth(),
710
693
  height: shape.getHeigth(),
711
694
  line_width: shape.getLineWidth(),
712
695
  color: shape.getColor(),
713
- });
696
+ };
697
+
698
+ rectangles.push(rectangle);
714
699
  });
715
700
 
716
701
  return rectangles;
717
702
  }
718
703
 
719
- private getMarkupEllipses() {
704
+ private getMarkupEllipses(): Array<IEllipse> {
720
705
  const ellipses = [];
721
- this.konvaLayerFind("Ellipse").forEach((ellipse) => {
722
- const position = ellipse.position();
706
+
707
+ this.konvaLayerFind("Ellipse").forEach((ref) => {
708
+ const position = ref.position();
723
709
  const worldPoint = this._worldTransformer.screenToWorld(position);
724
710
 
725
- const shape = new KonvaEllipse(null, ellipse);
726
- ellipses.push({
711
+ const shape = new KonvaEllipse(null, ref);
712
+ const ellipse: IEllipse = {
727
713
  id: shape.id(),
728
714
  position: worldPoint,
729
- radius: { x: ellipse.getRadiusX(), y: ellipse.getRadiusY() },
715
+ radius: { x: ref.getRadiusX(), y: ref.getRadiusY() },
730
716
  line_width: shape.getLineWidth(),
731
717
  color: shape.getColor(),
732
- });
718
+ };
719
+
720
+ ellipses.push(ellipse);
733
721
  });
734
722
 
735
723
  return ellipses;
736
724
  }
737
725
 
738
- private getMarkupArrows() {
726
+ private getMarkupArrows(): Array<IArrow> {
739
727
  const arrows = [];
740
- this.konvaLayerFind("Arrow").forEach((arrow) => {
728
+
729
+ this.konvaLayerFind("Arrow").forEach((ref) => {
741
730
  // we need getAbsoluteTransform because inside Konva position starts from {0, 0}
742
- const absoluteTransform = arrow.getAbsoluteTransform();
731
+ const absoluteTransform = ref.getAbsoluteTransform();
743
732
 
744
- const atStartPoint = absoluteTransform.point({ x: arrow.points()[0], y: arrow.points()[1] });
733
+ const atStartPoint = absoluteTransform.point({ x: ref.points()[0], y: ref.points()[1] });
745
734
  const worldStartPoint = this._worldTransformer.screenToWorld(atStartPoint);
746
735
 
747
- const atEndPoint = absoluteTransform.point({ x: arrow.points()[2], y: arrow.points()[3] });
736
+ const atEndPoint = absoluteTransform.point({ x: ref.points()[2], y: ref.points()[3] });
748
737
  const worldEndPoint = this._worldTransformer.screenToWorld(atEndPoint);
749
738
 
750
- const shape = new KonvaArrow(null, arrow);
751
- arrows.push({
739
+ const shape = new KonvaArrow(null, ref);
740
+ const arrow: IArrow = {
752
741
  id: shape.id(),
753
742
  start: worldStartPoint,
754
743
  end: worldEndPoint,
755
744
  color: shape.getColor(),
756
- });
745
+ };
746
+
747
+ arrows.push(arrow);
757
748
  });
758
749
 
759
750
  return arrows;
760
751
  }
761
752
 
762
- private getMarkupImages() {
753
+ private getMarkupImages(): Array<IImage> {
763
754
  const images = [];
764
- this.konvaLayerFind("Image").forEach((image) => {
765
- const position = image.position();
755
+
756
+ this.konvaLayerFind("Image").forEach((ref) => {
757
+ const position = ref.position();
766
758
  const worldPoint = this._worldTransformer.screenToWorld(position);
767
759
 
768
- const shape = new KonvaImage(null, image);
769
- images.push({
760
+ const shape = new KonvaImage(null, ref);
761
+ const image: IImage = {
770
762
  id: shape.id(),
771
763
  position: worldPoint,
772
764
  src: shape.getSrc(),
773
765
  width: shape.getWidth(),
774
766
  height: shape.getHeight(),
775
- });
767
+ };
768
+
769
+ images.push(image);
776
770
  });
777
771
 
778
772
  return images;
779
773
  }
780
774
 
781
- private getMarkupClouds() {
775
+ private getMarkupClouds(): Array<ICloud> {
782
776
  const clouds = [];
783
- this.konvaLayerFind("Cloud").forEach((cloud) => {
784
- const position = cloud.position();
777
+
778
+ this.konvaLayerFind("Cloud").forEach((ref) => {
779
+ const position = ref.position();
785
780
  const worldPoint = this._worldTransformer.screenToWorld(position);
786
781
 
787
- const shape = new KonvaCloud(null, cloud);
788
- clouds.push({
782
+ const shape = new KonvaCloud(null, ref);
783
+ const cloud: ICloud = {
789
784
  id: shape.id(),
790
785
  position: worldPoint,
791
786
  width: shape.getWidth(),
792
787
  height: shape.getHeigth(),
793
788
  line_width: shape.getLineWidth(),
794
789
  color: shape.getColor(),
795
- });
796
- });
797
-
798
- return clouds;
799
- }
800
-
801
- private loadMarkup(viewpoint: IViewpoint) {
802
- viewpoint.lines?.forEach((vpLine) => {
803
- const linePoints = [];
804
- vpLine.points.forEach((point) => {
805
- const screenPoint = this._worldTransformer.worldToScreen(point);
806
- linePoints.push(screenPoint.x);
807
- linePoints.push(screenPoint.y);
808
- });
809
-
810
- this.addLine(linePoints, vpLine.color, vpLine.type as MarkupLineType, vpLine.width, vpLine.id);
811
- });
812
-
813
- viewpoint.texts?.forEach((vpText) => {
814
- const screenPoint = this._worldTransformer.worldToScreen(vpText.position);
815
- this.addText(vpText.text, screenPoint, vpText.angle, vpText.color, vpText.text_size, vpText.font_size, vpText.id);
816
- });
817
-
818
- viewpoint.rectangles?.forEach((vpRect) => {
819
- const screenPoint = this._worldTransformer.worldToScreen(vpRect.position);
820
- this.addRectangle(screenPoint, vpRect.width, vpRect.height, vpRect.line_width, vpRect.color, vpRect.id);
821
- });
822
-
823
- viewpoint.ellipses?.forEach((vpEllipse) => {
824
- const screenPoint = this._worldTransformer.worldToScreen(vpEllipse.position);
825
- this.addEllipse(screenPoint, vpEllipse.radius, vpEllipse.line_width, vpEllipse.color, vpEllipse.id);
826
- });
827
-
828
- viewpoint.arrows?.forEach((vpArrow) => {
829
- const startPoint = this._worldTransformer.worldToScreen(vpArrow.start);
830
- const endPoint = this._worldTransformer.worldToScreen(vpArrow.end);
831
- this.addArrow(startPoint, endPoint, vpArrow.color, vpArrow.id);
832
- });
790
+ };
833
791
 
834
- viewpoint.clouds?.forEach((vpCloud) => {
835
- const screenPoint = this._worldTransformer.worldToScreen(vpCloud.position);
836
- this.addCloud(screenPoint, vpCloud.width, vpCloud.height, vpCloud.line_width, vpCloud.color, vpCloud.id);
792
+ clouds.push(cloud);
837
793
  });
838
794
 
839
- viewpoint.images?.forEach((vpImage) => {
840
- const screenPoint = this._worldTransformer.worldToScreen(vpImage.position);
841
- this.addImage(screenPoint, vpImage.src, vpImage.width, vpImage.height, vpImage.id);
842
- });
795
+ return clouds;
843
796
  }
844
797
 
845
798
  private combineMarkupWithDrawing() {
846
799
  this.clearSelected();
847
800
 
848
801
  const tempCanvas = document.createElement("canvas");
849
- tempCanvas.width = this._konvaStage.width();
850
- tempCanvas.height = this._konvaStage.height();
802
+ if (this._konvaStage) {
803
+ tempCanvas.width = this._konvaStage.width();
804
+ tempCanvas.height = this._konvaStage.height();
851
805
 
852
- const ctx = tempCanvas.getContext("2d");
853
- if (this._container instanceof HTMLCanvasElement) ctx.drawImage(this._container, 0, 0);
854
- ctx.drawImage(this._konvaStage.toCanvas({ pixelRatio: window.devicePixelRatio }), 0, 0);
806
+ const ctx = tempCanvas.getContext("2d");
807
+ if (this._container instanceof HTMLCanvasElement) ctx.drawImage(this._container, 0, 0);
808
+ ctx.drawImage(this._konvaStage.toCanvas({ pixelRatio: window.devicePixelRatio }), 0, 0);
809
+ }
855
810
 
856
811
  return tempCanvas.toDataURL("image/jpeg", 0.25);
857
812
  }
@@ -878,8 +833,7 @@ export class KonvaMarkup implements IMarkup {
878
833
  id,
879
834
  });
880
835
 
881
- const obj = konvaLine.ref();
882
- this._konvaLayer.add(obj);
836
+ this.addObject(konvaLine);
883
837
  return konvaLine;
884
838
  }
885
839
 
@@ -968,7 +922,7 @@ export class KonvaMarkup implements IMarkup {
968
922
  }
969
923
 
970
924
  private addText(
971
- specifiedText: string,
925
+ text: string,
972
926
  position: Konva.Vector2d,
973
927
  angle?: number,
974
928
  color?: string,
@@ -976,37 +930,33 @@ export class KonvaMarkup implements IMarkup {
976
930
  fontSize?: number,
977
931
  id?: string
978
932
  ): KonvaText | void {
979
- const trNodes = this._konvaTransformer.nodes();
980
- if (trNodes.length > 0) {
981
- // in case of edit - remove old Konva.Text object
982
- trNodes[0].destroy();
983
- this._konvaTransformer.nodes([]);
984
- }
933
+ if (!text) return;
985
934
 
986
- this.removeTextInput();
935
+ // in case of edit - remove old Konva.Text object
936
+ this.getSelectedObjects().at(0)?.delete();
987
937
 
988
- if (specifiedText) {
989
- const tolerance = 1.0e-6;
938
+ this.clearSelected();
939
+ this.removeTextInput();
990
940
 
991
- // in case we have old viewpoint without font_size
992
- if (textSize && textSize > tolerance && (!fontSize || fontSize < tolerance)) {
993
- const size = 0.02;
994
- const scale = this._worldTransformer.getScale();
995
- fontSize = textSize / (scale.y / size) / 34;
996
- }
941
+ // in case we have old viewpoint without font_size
942
+ const tolerance = 1.0e-6;
943
+ if (textSize && textSize > tolerance && (!fontSize || fontSize < tolerance)) {
944
+ const size = 0.02;
945
+ const scale = this._worldTransformer.getScale();
946
+ fontSize = textSize / (scale.y / size) / 34;
947
+ }
997
948
 
998
- const konvaText = new KonvaText({
999
- position: { x: position.x, y: position.y },
1000
- text: specifiedText,
1001
- rotation: angle,
1002
- fontSize: fontSize || this.fontSize,
1003
- color: color || this._markupColor.HexColor,
1004
- id,
1005
- });
949
+ const konvaText = new KonvaText({
950
+ position: { x: position.x, y: position.y },
951
+ text,
952
+ rotation: angle,
953
+ fontSize: fontSize || this.fontSize,
954
+ color: color || this._markupColor.HexColor,
955
+ id,
956
+ });
1006
957
 
1007
- this._konvaLayer.add(konvaText.ref());
1008
- return konvaText;
1009
- }
958
+ this.addObject(konvaText);
959
+ return konvaText;
1010
960
  }
1011
961
 
1012
962
  private addRectangle(
@@ -1028,8 +978,7 @@ export class KonvaMarkup implements IMarkup {
1028
978
  id,
1029
979
  });
1030
980
 
1031
- const obj = konvaRectangle.ref();
1032
- this._konvaLayer.add(obj);
981
+ this.addObject(konvaRectangle);
1033
982
  return konvaRectangle;
1034
983
  }
1035
984
 
@@ -1050,8 +999,7 @@ export class KonvaMarkup implements IMarkup {
1050
999
  id,
1051
1000
  });
1052
1001
 
1053
- const obj = konvaEllipse.ref();
1054
- this._konvaLayer.add(obj);
1002
+ this.addObject(konvaEllipse);
1055
1003
  return konvaEllipse;
1056
1004
  }
1057
1005
 
@@ -1070,8 +1018,7 @@ export class KonvaMarkup implements IMarkup {
1070
1018
  id,
1071
1019
  });
1072
1020
 
1073
- const obj = konvaArrow.ref();
1074
- this._konvaLayer.add(obj);
1021
+ this.addObject(konvaArrow);
1075
1022
  return konvaArrow;
1076
1023
  }
1077
1024
 
@@ -1094,8 +1041,7 @@ export class KonvaMarkup implements IMarkup {
1094
1041
  id,
1095
1042
  });
1096
1043
 
1097
- const obj = konvaCloud.ref();
1098
- this._konvaLayer.add(obj);
1044
+ this.addObject(konvaCloud);
1099
1045
  return konvaCloud;
1100
1046
  }
1101
1047
 
@@ -1106,32 +1052,23 @@ export class KonvaMarkup implements IMarkup {
1106
1052
  height?: number,
1107
1053
  id?: string
1108
1054
  ): KonvaImage | void {
1109
- if (!position) return;
1055
+ if (!position || !src) return;
1110
1056
 
1111
- let konvaImage: KonvaImage;
1112
-
1113
- if (src) {
1114
- konvaImage = new KonvaImage({
1115
- position,
1116
- src,
1117
- width,
1118
- height,
1119
- id,
1120
- });
1121
-
1122
- const obj = konvaImage.ref();
1123
- this._konvaLayer.add(obj);
1124
-
1125
- const trNodes = this._konvaTransformer.nodes();
1126
- if (trNodes.length > 0) {
1127
- // in case of edit - remove old Image placeholder object
1128
- trNodes[0].destroy();
1129
- this._konvaTransformer.nodes([]);
1130
- }
1131
- }
1057
+ // in case of edit - remove old Image placeholder object
1058
+ this.getSelectedObjects().at(0)?.delete();
1132
1059
 
1060
+ this.clearSelected();
1133
1061
  this.removeImageInput();
1134
1062
 
1063
+ const konvaImage = new KonvaImage({
1064
+ position,
1065
+ src,
1066
+ width,
1067
+ height,
1068
+ id,
1069
+ });
1070
+
1071
+ this.addObject(konvaImage);
1135
1072
  return konvaImage;
1136
1073
  }
1137
1074
  }