@inweb/markup 25.7.9 → 25.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inweb/markup",
3
- "version": "25.7.9",
3
+ "version": "25.8.0",
4
4
  "description": "JavaScript 2D markups",
5
5
  "homepage": "https://cloud.opendesign.com/docs/index.html",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -26,8 +26,8 @@
26
26
  "docs": "typedoc"
27
27
  },
28
28
  "dependencies": {
29
- "@inweb/eventemitter2": "~25.7.9",
30
- "@inweb/viewer-core": "~25.7.9"
29
+ "@inweb/eventemitter2": "~25.8.0",
30
+ "@inweb/viewer-core": "~25.8.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "canvas": "^2.11.2",
@@ -132,6 +132,14 @@ export interface IMarkup {
132
132
  */
133
133
  getViewpoint(): IViewpoint;
134
134
 
135
+ /**
136
+ * Enables mouse interactions to select or draw markups.
137
+ *
138
+ * @param mode - Edit mode. Matches the type of markup object being created or object
139
+ * selecting mode. To exit edit mode provide this to `false`.
140
+ */
141
+ enableEditMode(mode: MarkupMode | false): this;
142
+
135
143
  /**
136
144
  * Create a Markup object.
137
145
  *
@@ -25,7 +25,7 @@ import Konva from "konva";
25
25
  import { IEventEmitter } from "@inweb/eventemitter2";
26
26
  import { ChangeActiveDraggerEvent, IViewpoint, PanEvent } from "@inweb/viewer-core";
27
27
 
28
- import { IMarkup } from "../IMarkup";
28
+ import { IMarkup, MarkupMode } from "../IMarkup";
29
29
  import { IWorldTransform } from "../IWorldTransform";
30
30
  import { IMarkupObject } from "../IMarkupObject";
31
31
  import { IMarkupColorable } from "../IMarkupColorable";
@@ -46,31 +46,37 @@ const MarkupMode2Konva = {
46
46
  },
47
47
  Line: {
48
48
  name: "Line",
49
- initializer: (ref: any) => new KonvaLine(null, ref),
49
+ initializer: (ref: any, params = null) => new KonvaLine(params, ref),
50
+ zIndex: 1,
50
51
  },
51
52
  Text: {
52
53
  name: "Text",
53
- initializer: (ref: any) => new KonvaText(null, ref),
54
+ initializer: (ref: any, params = null) => new KonvaText(params, ref),
54
55
  },
55
56
  Rectangle: {
56
57
  name: "Rect",
57
- initializer: (ref: any) => new KonvaRectangle(null, ref),
58
+ initializer: (ref: any, params = null) => new KonvaRectangle(params, ref),
59
+ zIndex: 1,
58
60
  },
59
61
  Ellipse: {
60
62
  name: "Ellipse",
61
- initializer: (ref: any) => new KonvaEllipse(null, ref),
63
+ initializer: (ref: any, params = null) => new KonvaEllipse(params, ref),
64
+ zIndex: 1,
62
65
  },
63
66
  Arrow: {
64
67
  name: "Arrow",
65
- initializer: (ref: any) => new KonvaArrow(null, ref),
68
+ initializer: (ref: any, params = null) => new KonvaArrow(params, ref),
69
+ zIndex: 1,
66
70
  },
67
71
  Image: {
68
72
  name: "Image",
69
- initializer: (ref: any) => new KonvaImage(null, ref),
73
+ initializer: (ref: any, params = null) => new KonvaImage(params, ref),
74
+ zIndex: 0,
70
75
  },
71
76
  Cloud: {
72
77
  name: "Cloud",
73
78
  initializer: (ref: any) => new KonvaCloud(null, ref),
79
+ zIndex: 1,
74
80
  },
75
81
  };
76
82
 
@@ -84,7 +90,7 @@ export class KonvaMarkup implements IMarkup {
84
90
  private _container: HTMLElement;
85
91
  private _pointerEvents: string[];
86
92
  private _markupIsActive = false;
87
- private _markupMode: string;
93
+ private _markupMode: MarkupMode;
88
94
  private _markupColor = new MarkupColor(255, 0, 0);
89
95
  private _konvaStage: Konva.Stage;
90
96
  private _konvaLayer: Konva.Layer;
@@ -187,14 +193,7 @@ export class KonvaMarkup implements IMarkup {
187
193
  this.removeTextInput();
188
194
  this.removeImageInput();
189
195
 
190
- const konvaShape = MarkupMode2Konva[draggerName];
191
- if (konvaShape) {
192
- this._markupMode = draggerName;
193
- this._markupIsActive = true;
194
- } else {
195
- this._markupIsActive = false;
196
- this._konvaTransformer.nodes([]);
197
- }
196
+ this.enableEditMode(draggerName as MarkupMode);
198
197
  };
199
198
 
200
199
  resizeContainer = (entries: ResizeObserverEntry[]) => {
@@ -209,10 +208,7 @@ export class KonvaMarkup implements IMarkup {
209
208
  pan = (event: PanEvent) => {
210
209
  const dX = event.dX / window.devicePixelRatio;
211
210
  const dY = event.dY / window.devicePixelRatio;
212
-
213
- Object.keys(MarkupMode2Konva).forEach((mode) =>
214
- this.konvaLayerFind(mode).forEach((ref) => ref.move({ x: dX, y: dY }))
215
- );
211
+ this.getObjects().forEach((obj) => obj.ref().move({ x: dX, y: dY }));
216
212
  };
217
213
 
218
214
  redirectToViewer = (event: any) => {
@@ -224,8 +220,8 @@ export class KonvaMarkup implements IMarkup {
224
220
  clearOverlay(): void {
225
221
  this.removeTextInput();
226
222
  this.removeImageInput();
227
- this._konvaTransformer.nodes([]);
228
- Object.keys(MarkupMode2Konva).forEach((mode) => this.konvaLayerFind(mode).forEach((ref) => ref.destroy()));
223
+ this.clearSelected();
224
+ this.getObjects().forEach((obj) => obj.ref().destroy());
229
225
  }
230
226
 
231
227
  getMarkupColor(): { r: number; g: number; b: number } {
@@ -236,25 +232,21 @@ export class KonvaMarkup implements IMarkup {
236
232
  this._markupColor.setColor(r, g, b);
237
233
  }
238
234
 
239
- colorizeAllMarkup(r = 255, g = 0, b = 0): void {
240
- const hex = new MarkupColor(r, g, b).HexColor;
241
- Object.keys(MarkupMode2Konva).forEach((mode) => {
242
- this.konvaLayerFind(mode).forEach((ref) => {
243
- const konvaShape = MarkupMode2Konva[mode];
244
- const konvaObj = konvaShape.initializer(ref);
245
- if (konvaObj.setColor) konvaObj.setColor(hex);
246
- });
235
+ colorizeAllMarkup(r: number, g: number, b: number): void {
236
+ const hexColor = new MarkupColor(r, g, b).HexColor;
237
+ this.getObjects().forEach((obj) => {
238
+ const colorable = obj as unknown as IMarkupColorable;
239
+ if (colorable && colorable.setColor) colorable.setColor(hexColor);
247
240
  });
248
241
 
249
242
  this._konvaLayer.draw();
250
243
  }
251
244
 
252
245
  colorizeSelectedMarkups(r: number, g: number, b: number): void {
246
+ const hexColor = new MarkupColor(r, g, b).HexColor;
253
247
  this.getSelectedObjects().forEach((obj) => {
254
248
  const colorable = obj as unknown as IMarkupColorable;
255
- if (colorable && colorable.setColor) {
256
- colorable.setColor(new MarkupColor(r, g, b).HexColor);
257
- }
249
+ if (colorable && colorable.setColor) colorable.setColor(hexColor);
258
250
  });
259
251
  }
260
252
 
@@ -290,116 +282,51 @@ export class KonvaMarkup implements IMarkup {
290
282
  return viewpoint;
291
283
  }
292
284
 
293
- createObject(type: string, params: any): IMarkupObject {
294
- let object = null;
295
- let zIndex = this._zIndex;
296
-
297
- // TODO: factory?
298
- switch (type.toLocaleLowerCase()) {
299
- case "line":
300
- object = new KonvaLine(params);
301
- zIndex = 1;
302
- break;
303
- case "text":
304
- object = new KonvaText(params);
305
- break;
306
- case "rectangle":
307
- object = new KonvaRectangle(params);
308
- zIndex = 1;
309
- break;
310
- case "ellipse":
311
- object = new KonvaEllipse(params);
312
- zIndex = 1;
313
- break;
314
- case "arrow":
315
- object = new KonvaArrow(params);
316
- break;
317
- case "image":
318
- object = new KonvaImage(params);
319
- zIndex = 0;
320
- break;
321
- case "cloud":
322
- object = new KonvaCloud(params);
323
- zIndex = 1;
324
- break;
325
- default:
326
- throw new Error("Markup CreateObject - unsupported type has been detected.");
285
+ enableEditMode(mode: MarkupMode | false): this {
286
+ if (!mode || !MarkupMode2Konva[mode]) {
287
+ this.clearSelected();
288
+ this._markupIsActive = false;
289
+ } else {
290
+ this._markupMode = mode;
291
+ this._markupIsActive = true;
327
292
  }
293
+ return this;
294
+ }
328
295
 
296
+ createObject(type: string, params: any): IMarkupObject {
297
+ const konvaShape = MarkupMode2Konva[type];
298
+ if (!konvaShape || !konvaShape.initializer)
299
+ throw new Error(`Markup CreateObject - unsupported markup type ${type}`);
300
+
301
+ const object = konvaShape.initializer(null, params);
329
302
  this.addObject(object);
330
303
 
331
- // Set zIndex only when shape has been added to Layer else we will get "Konva warning: Node has no parent. zIndex parameter is ignored."
332
- object.setZIndex(zIndex);
304
+ // Set zIndex only when shape has been added to Layer else we will get
305
+ // "Konva warning: Node has no parent. zIndex parameter is ignored."
306
+ object.setZIndex(konvaShape.zIndex ?? this._zIndex);
333
307
  this._zIndex++;
308
+
334
309
  return object;
335
310
  }
336
311
 
337
312
  getObjects(): IMarkupObject[] {
338
313
  const objects = [];
339
- this.konvaLayerFind("Line").forEach((line) => {
340
- objects.push(new KonvaLine(null, line));
341
- });
342
-
343
- this.konvaLayerFind("Text").forEach((text) => {
344
- objects.push(new KonvaText(null, text));
345
- });
346
-
347
- this.konvaLayerFind("Rectangle").forEach((rectangle) => {
348
- objects.push(new KonvaRectangle(null, rectangle));
349
- });
350
-
351
- this.konvaLayerFind("Ellipse").forEach((ellipse) => {
352
- objects.push(new KonvaEllipse(null, ellipse));
353
- });
354
-
355
- this.konvaLayerFind("Arrow").forEach((arrow) => {
356
- objects.push(new KonvaArrow(null, arrow));
357
- });
358
-
359
- this.konvaLayerFind("Image").forEach((image) => {
360
- objects.push(new KonvaImage(null, image));
361
- });
362
-
363
- this.konvaLayerFind("Cloud").forEach((cloud) => {
364
- objects.push(new KonvaCloud(null, cloud));
314
+ Object.keys(MarkupMode2Konva).forEach((type) => {
315
+ const konvaShape = MarkupMode2Konva[type];
316
+ this.konvaLayerFind(type).forEach((ref) => objects.push(konvaShape.initializer(ref)));
365
317
  });
366
-
367
318
  return objects;
368
319
  }
369
320
 
370
321
  getSelectedObjects(): IMarkupObject[] {
371
- const objects = [];
372
-
373
- this._konvaTransformer.nodes().forEach((obj) => {
374
- const konvaShapeName = obj.className;
375
- switch (konvaShapeName) {
376
- case "Line":
377
- objects.push(new KonvaLine(null, obj));
378
- break;
379
- case "Text":
380
- objects.push(new KonvaText(null, obj));
381
- break;
382
- case "Rect":
383
- objects.push(new KonvaRectangle(null, obj));
384
- break;
385
- case "Ellipse":
386
- objects.push(new KonvaEllipse(null, obj));
387
- break;
388
- case "Arrow":
389
- objects.push(new KonvaArrow(null, obj));
390
- break;
391
- case "Image":
392
- objects.push(new KonvaImage(null, obj));
393
- break;
394
- case "Cloud":
395
- objects.push(new KonvaCloud(null, obj));
396
- break;
397
- default:
398
- break;
399
- }
400
- });
401
-
402
- return objects;
322
+ return this._konvaTransformer
323
+ .nodes()
324
+ .map((ref) => {
325
+ const name = ref.className;
326
+ const konvaShape = Object.values(MarkupMode2Konva).find((shape) => shape.name === name);
327
+ return konvaShape ? konvaShape.initializer(ref) : null;
328
+ })
329
+ .filter((x) => x);
403
330
  }
404
331
 
405
332
  selectObjects(objects: IMarkupObject[]) {
@@ -470,8 +397,8 @@ export class KonvaMarkup implements IMarkup {
470
397
  this._konvaLayer.add(object.ref());
471
398
  }
472
399
 
473
- private konvaLayerFind(markupShape: string): any {
474
- const konvaShape = MarkupMode2Konva[markupShape];
400
+ private konvaLayerFind(type: string): any {
401
+ const konvaShape = MarkupMode2Konva[type];
475
402
  if (konvaShape && konvaShape.initializer) {
476
403
  // for "draggable" Konva uses Rectangles in Transformer. We need only Shapes from layer.
477
404
  return this._konvaLayer.find(konvaShape.name).filter((ref) => ref.parent === this._konvaLayer);