@inweb/markup 26.4.0 → 26.5.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.
Files changed (40) hide show
  1. package/dist/markup.js +636 -137
  2. package/dist/markup.js.map +1 -1
  3. package/dist/markup.min.js +1 -1
  4. package/dist/markup.module.js +772 -151
  5. package/dist/markup.module.js.map +1 -1
  6. package/lib/markup/IMarkupArrow.d.ts +8 -8
  7. package/lib/markup/IMarkupCloud.d.ts +12 -5
  8. package/lib/markup/IMarkupEllipse.d.ts +19 -4
  9. package/lib/markup/IMarkupImage.d.ts +15 -7
  10. package/lib/markup/IMarkupLine.d.ts +2 -2
  11. package/lib/markup/IMarkupObject.d.ts +4 -0
  12. package/lib/markup/IMarkupRectangle.d.ts +12 -5
  13. package/lib/markup/IMarkupText.d.ts +3 -3
  14. package/lib/markup/Konva/KonvaArrow.d.ts +4 -1
  15. package/lib/markup/Konva/KonvaCloud.d.ts +4 -1
  16. package/lib/markup/Konva/KonvaEllipse.d.ts +4 -1
  17. package/lib/markup/Konva/KonvaImage.d.ts +4 -1
  18. package/lib/markup/Konva/KonvaLine.d.ts +4 -1
  19. package/lib/markup/Konva/KonvaMarkup.d.ts +2 -2
  20. package/lib/markup/Konva/KonvaRectangle.d.ts +4 -1
  21. package/lib/markup/Konva/KonvaText.d.ts +4 -1
  22. package/lib/markup/Utils.d.ts +7 -0
  23. package/package.json +3 -3
  24. package/src/markup/IMarkupArrow.ts +8 -8
  25. package/src/markup/IMarkupCloud.ts +10 -5
  26. package/src/markup/IMarkupEllipse.ts +15 -4
  27. package/src/markup/IMarkupImage.ts +13 -7
  28. package/src/markup/IMarkupLine.ts +2 -2
  29. package/src/markup/IMarkupObject.ts +5 -0
  30. package/src/markup/IMarkupRectangle.ts +10 -5
  31. package/src/markup/IMarkupText.ts +3 -3
  32. package/src/markup/Konva/KonvaArrow.ts +49 -4
  33. package/src/markup/Konva/KonvaCloud.ts +113 -11
  34. package/src/markup/Konva/KonvaEllipse.ts +110 -3
  35. package/src/markup/Konva/KonvaImage.ts +101 -2
  36. package/src/markup/Konva/KonvaLine.ts +97 -3
  37. package/src/markup/Konva/KonvaMarkup.ts +216 -172
  38. package/src/markup/Konva/KonvaRectangle.ts +106 -4
  39. package/src/markup/Konva/KonvaText.ts +61 -2
  40. package/src/markup/Utils.ts +3 -0
@@ -28,12 +28,12 @@ import { IMarkupObject } from "./IMarkupObject";
28
28
  */
29
29
  export interface IMarkupImage extends IMarkupObject {
30
30
  /**
31
- * Returns the coordinates of the top-left point (position) of the image.
31
+ * Returns the screen coordinates of the top-left point (position) of the image.
32
32
  */
33
33
  getPosition(): { x: number; y: number };
34
34
 
35
35
  /**
36
- * Sets the coordinates of the top-left point (position) of the image.
36
+ * Sets the screen coordinates of the top-left point (position) of the image.
37
37
  */
38
38
  setPosition(x: number, y: number): void;
39
39
 
@@ -79,10 +79,16 @@ export interface IMarkupImage extends IMarkupObject {
79
79
  */
80
80
  export interface IMarkupImageParams {
81
81
  /**
82
- * Coordinates of the top-left point (position) of the image.
82
+ * Screen coordinates of the top-left point (position) of the image.
83
83
  */
84
84
  position?: { x: number; y: number };
85
85
 
86
+ /**
87
+ * Screen coordinates of the bottom-right point (position) of the image. Specify 0 to set widt and
88
+ * height of the source image.
89
+ */
90
+ position2?: { x: number; y: number };
91
+
86
92
  /**
87
93
  * Image source as a base64-encoded
88
94
  * {@link https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Data_URIs | Data URL}.
@@ -90,16 +96,16 @@ export interface IMarkupImageParams {
90
96
  src?: string;
91
97
 
92
98
  /**
93
- * Width of the image. The original image is scaled to this width. Specify 0 to set width of the source
94
- * image.
99
+ * Deprecated. Width of the image. The original image is scaled to this width. Specify 0 to set width
100
+ * of the source image. Ignored if {@link position2} is defined.
95
101
  *
96
102
  * @default 0
97
103
  */
98
104
  width?: number;
99
105
 
100
106
  /**
101
- * Height of the image. The original image is scaled to this height. Specify 0 to set height of the
102
- * source image.
107
+ * Deprecated. Height of the image. The original image is scaled to this height. Specify 0 to set
108
+ * height of the source image. Ignored if {@link position2} is defined.
103
109
  *
104
110
  * @default 0
105
111
  */
@@ -34,7 +34,7 @@ export type MarkupLineType = "solid" | "dot" | "dash";
34
34
  */
35
35
  export interface IMarkupLine extends IMarkupObject, IMarkupColorable {
36
36
  /**
37
- * Returns the coordinates of the line points as a flat array [x1, y1, x2, y2, ...].
37
+ * Returns the screen coordinates of the line points as a flat array [x1, y1, x2, y2, ...].
38
38
  */
39
39
  getPoints(): number[];
40
40
 
@@ -73,7 +73,7 @@ export interface IMarkupLine extends IMarkupObject, IMarkupColorable {
73
73
  */
74
74
  export interface IMarkupLineParams {
75
75
  /**
76
- * Array of line points.
76
+ * Array of screen points of the line.
77
77
  */
78
78
  points?: { x: number; y: number }[];
79
79
 
@@ -81,6 +81,11 @@ export interface IMarkupObject {
81
81
  */
82
82
  setZIndex(zIndex: number): void;
83
83
 
84
+ /**
85
+ * Update current screen coordinates with internal WCS-based. Only for resize.
86
+ */
87
+ updateScreenCoordinates(): void;
88
+
84
89
  /**
85
90
  * Deletes the current object.
86
91
  */
@@ -29,12 +29,12 @@ import { IMarkupColorable } from "./IMarkupColorable";
29
29
  */
30
30
  export interface IMarkupRectangle extends IMarkupObject, IMarkupColorable {
31
31
  /**
32
- * Returns the coordinates of the top-left point (position) of the rectangle.
32
+ * Returns the screen coordinates of the top-left point (position) of the rectangle.
33
33
  */
34
34
  getPosition(): { x: number; y: number };
35
35
 
36
36
  /**
37
- * Sets the coordinates of the top-left point (position) of the rectangle.
37
+ * Sets the screen coordinates of the top-left point (position) of the rectangle.
38
38
  */
39
39
  setPosition(x: number, y: number): void;
40
40
 
@@ -74,19 +74,24 @@ export interface IMarkupRectangle extends IMarkupObject, IMarkupColorable {
74
74
  */
75
75
  export interface IMarkupRectangleParams {
76
76
  /**
77
- * Coordinates of the top-left point (position) of the rectangle.
77
+ * Screen coordinates of the top-left point (position) of the rectangle.
78
78
  */
79
79
  position?: { x: number; y: number };
80
80
 
81
81
  /**
82
- * Width of the rectangle.
82
+ * Screen coordinates of the bottom-right point (position) of the rectangle.
83
+ */
84
+ position2?: { x: number; y: number };
85
+
86
+ /**
87
+ * Width of the rectangle. Ignored if {@link position2} is defined.
83
88
  *
84
89
  * @default 200
85
90
  */
86
91
  width?: number;
87
92
 
88
93
  /**
89
- * Height of the rectangle.
94
+ * Height of the rectangle. Ignored if {@link position2} is defined.
90
95
  *
91
96
  * @default 200
92
97
  */
@@ -39,12 +39,12 @@ export interface IMarkupText extends IMarkupObject, IMarkupColorable {
39
39
  setText(text: string): void;
40
40
 
41
41
  /**
42
- * Returns the coordinates of the top-left point (position) of the text.
42
+ * Returns the screen coordinates of the top-left point (position) of the text.
43
43
  */
44
44
  getPosition(): { x: number; y: number };
45
45
 
46
46
  /**
47
- * Sets the coordinates of the top-left point (position) of the text.
47
+ * Sets the screen coordinates of the top-left point (position) of the text.
48
48
  */
49
49
  setPosition(x: number, y: number): void;
50
50
 
@@ -64,7 +64,7 @@ export interface IMarkupText extends IMarkupObject, IMarkupColorable {
64
64
  */
65
65
  export interface IMarkupTextParams {
66
66
  /**
67
- * Coordinates of the top-left point (position) of the text.
67
+ * Screen coordinates of the top-left point (position) of the text.
68
68
  */
69
69
  position?: { x: number; y: number };
70
70
 
@@ -23,13 +23,24 @@
23
23
 
24
24
  import Konva from "konva";
25
25
  import { IMarkupArrow, IMarkupArrowParams } from "../IMarkupArrow";
26
+ import { IWorldTransform } from "../IWorldTransform";
27
+ import { WorldTransform } from "../WorldTransform";
26
28
 
27
29
  export class KonvaArrow implements IMarkupArrow {
28
30
  private _ref: Konva.Arrow;
31
+ private _worldTransformer: IWorldTransform;
32
+
33
+ constructor(params: IMarkupArrowParams, ref = null, worldTransformer = new WorldTransform()) {
34
+ this._worldTransformer = worldTransformer;
29
35
 
30
- constructor(params: IMarkupArrowParams, ref = null) {
31
36
  if (ref) {
32
37
  this._ref = ref;
38
+ const wcsStart = this._ref.getAttr("wcsStart");
39
+ const wcsEnd = this._ref.getAttr("wcsEnd");
40
+ if (!wcsStart)
41
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({ x: ref.points()[0], y: ref.points()[1] }));
42
+ if (!wcsEnd)
43
+ this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({ x: ref.points()[2], y: ref.points()[3] }));
33
44
  return;
34
45
  }
35
46
 
@@ -49,10 +60,28 @@ export class KonvaArrow implements IMarkupArrow {
49
60
  strokeScaleEnabled: false,
50
61
  });
51
62
 
52
- this._ref.on("transform", (e) => {
53
- const attrs = e.target.attrs;
63
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({ x: params.start.x, y: params.start.y }));
64
+ this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({ x: params.end.x, y: params.end.y }));
54
65
 
66
+ this._ref.on("transformend", (e) => {
67
+ const attrs = e.target.attrs;
55
68
  if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
69
+
70
+ const points = this._ref.points();
71
+ const absoluteTransform = this._ref.getAbsoluteTransform();
72
+ const transformStart = absoluteTransform.point({ x: points[0], y: points[1] });
73
+ const transformEnd = absoluteTransform.point({ x: points[2], y: points[3] });
74
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(transformStart));
75
+ this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld(transformEnd));
76
+ });
77
+
78
+ this._ref.on("dragend", (e) => {
79
+ const points = this._ref.points();
80
+ const absoluteTransform = e.target.getAbsoluteTransform();
81
+ const transformStart = absoluteTransform.point({ x: points[0], y: points[1] });
82
+ const transformEnd = absoluteTransform.point({ x: points[2], y: points[3] });
83
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(transformStart));
84
+ this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld(transformEnd));
56
85
  });
57
86
 
58
87
  this._ref.id(this._ref._id.toString());
@@ -99,7 +128,7 @@ export class KonvaArrow implements IMarkupArrow {
99
128
  this._ref.zIndex(zIndex);
100
129
  }
101
130
 
102
- delete() {
131
+ delete(): void {
103
132
  this._ref.destroy();
104
133
  this._ref = null;
105
134
  }
@@ -114,6 +143,8 @@ export class KonvaArrow implements IMarkupArrow {
114
143
 
115
144
  setPoints(points: { x: number; y: number }[]): void {
116
145
  if (points.length === 2) {
146
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({ x: points[0].x, y: points[0].y }));
147
+ this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({ x: points[1].x, y: points[1].y }));
117
148
  this._ref.points([points[0].x, points[0].y, points[1].x, points[1].y]);
118
149
  }
119
150
  }
@@ -126,6 +157,7 @@ export class KonvaArrow implements IMarkupArrow {
126
157
  setStartPoint(x: number, y: number): void {
127
158
  const points = this._ref.points();
128
159
  this._ref.points([x, y, points[2], points[3]]);
160
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({ x, y }));
129
161
  }
130
162
 
131
163
  getEndPoint(): { x: number; y: number } {
@@ -136,5 +168,18 @@ export class KonvaArrow implements IMarkupArrow {
136
168
  setEndPoint(x: number, y: number): void {
137
169
  const points = this._ref.points();
138
170
  this._ref.points([points[0], points[1], x, y]);
171
+ this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({ x, y }));
172
+ }
173
+
174
+ updateScreenCoordinates(): void {
175
+ let screenStartPoint = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsStart"));
176
+ let screenEndPoint = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsEnd"));
177
+
178
+ let invert = this._ref.getAbsoluteTransform().copy();
179
+ invert = invert.invert();
180
+ const startPoint = invert.point({ x: screenStartPoint.x, y: screenStartPoint.y });
181
+ const endPoint = invert.point({ x: screenEndPoint.x, y: screenEndPoint.y });
182
+
183
+ this._ref.points([startPoint.x, startPoint.y, endPoint.x, endPoint.y]);
139
184
  }
140
185
  }
@@ -1,19 +1,71 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
3
+ // All rights reserved.
4
+ //
5
+ // This software and its documentation and related materials are owned by
6
+ // the Alliance. The software may only be incorporated into application
7
+ // programs owned by members of the Alliance, subject to a signed
8
+ // Membership Agreement and Supplemental Software License Agreement with the
9
+ // Alliance. The structure and organization of this software are the valuable
10
+ // trade secrets of the Alliance and its suppliers. The software is also
11
+ // protected by copyright law and international treaty provisions. Application
12
+ // programs incorporating this software must include the following statement
13
+ // with their copyright notices:
14
+ //
15
+ // This application incorporates Open Design Alliance software pursuant to a
16
+ // license agreement with Open Design Alliance.
17
+ // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
18
+ // All rights reserved.
19
+ //
20
+ // By use of this software, its documentation or related materials, you
21
+ // acknowledge and accept the above terms.
22
+ ///////////////////////////////////////////////////////////////////////////////
23
+
1
24
  import Konva from "konva";
2
25
  import { IMarkupCloud, IMarkupCloudParams } from "../IMarkupCloud";
26
+ import { IWorldTransform } from "../IWorldTransform";
27
+ import { WorldTransform } from "../WorldTransform";
3
28
 
4
29
  export class KonvaCloud implements IMarkupCloud {
5
30
  private _ref: Konva.Shape;
31
+ private _worldTransformer: IWorldTransform;
32
+
33
+ constructor(params: IMarkupCloudParams, ref = null, worldTransformer = new WorldTransform()) {
34
+ this._worldTransformer = worldTransformer;
6
35
 
7
- constructor(params: IMarkupCloudParams, ref = null) {
8
36
  if (ref) {
9
37
  this._ref = ref;
38
+ const wcsStart = this._ref.getAttr("wcsStart");
39
+ const wcsEnd = this._ref.getAttr("wcsEnd");
40
+ if (!wcsStart) {
41
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({ x: ref.x(), y: ref.y() }));
42
+ }
43
+ if (!wcsEnd) {
44
+ const rightBottomPoint = { x: ref.x() + ref.width(), y: ref.y() + ref.height() };
45
+ this._ref.setAttr(
46
+ "wcsEnd",
47
+ this._worldTransformer.screenToWorld({ x: rightBottomPoint.x, y: rightBottomPoint.y })
48
+ );
49
+ }
10
50
  return;
11
51
  }
12
52
 
13
53
  if (!params) params = {};
14
54
  if (!params.position) params.position = { x: 0, y: 0 };
55
+ if (params.position2) {
56
+ params.width = params.position2.x - params.position.x;
57
+ params.height = params.position2.y - params.position.y;
58
+ } else {
59
+ if (!params.width || !params.height) {
60
+ params.position2 = { x: 200, y: 200 };
61
+ params.width = 200;
62
+ params.height = 200;
63
+ } else {
64
+ params.position2 = { x: params.position.x + params.width, y: params.position.y + params.height };
65
+ }
66
+ }
15
67
 
16
- const arcRadius = 16;
68
+ const ARC_RADIUS = 16;
17
69
 
18
70
  this._ref = new Konva.Shape({
19
71
  x: params.position.x,
@@ -63,9 +115,9 @@ export class KonvaCloud implements IMarkupCloud {
63
115
  const counterClockwise = pX > midPoint.x && pY > midPoint.y;
64
116
  for (let iArc = 0; iArc < arcCount; iArc++) {
65
117
  if (counterClockwise) {
66
- context.arc(pX, pY, arcRadius, endAngle, startAngle);
118
+ context.arc(pX, pY, ARC_RADIUS, endAngle, startAngle);
67
119
  } else {
68
- context.arc(pX, pY, arcRadius, startAngle, endAngle);
120
+ context.arc(pX, pY, ARC_RADIUS, startAngle, endAngle);
69
121
  }
70
122
 
71
123
  pX += dx / arcCount;
@@ -82,11 +134,12 @@ export class KonvaCloud implements IMarkupCloud {
82
134
 
83
135
  this._ref.className = "Cloud";
84
136
 
137
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({ x: params.position.x, y: params.position.y }));
138
+ this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({ x: params.position2.x, y: params.position2.y }));
139
+
85
140
  this._ref.on("transform", (e) => {
86
141
  const attrs = e.target.attrs;
87
142
 
88
- if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
89
-
90
143
  const scaleByX = Math.abs(attrs.scaleX - 1) > 10e-6;
91
144
  const scaleByY = Math.abs(attrs.scaleY - 1) > 10e-6;
92
145
 
@@ -112,12 +165,35 @@ export class KonvaCloud implements IMarkupCloud {
112
165
  this._ref.scale({ x: 1, y: 1 });
113
166
  });
114
167
 
168
+ this._ref.on("transformend", (e) => {
169
+ const attrs = e.target.attrs;
170
+ if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
171
+
172
+ const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
173
+ const position = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() });
174
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
175
+ this._ref.setAttr(
176
+ "wcsEnd",
177
+ this._worldTransformer.screenToWorld({ x: position.x + this._ref.width(), y: position.y + this._ref.height() })
178
+ );
179
+ });
180
+
181
+ this._ref.on("dragend", (e) => {
182
+ const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
183
+ const position = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() });
184
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
185
+ this._ref.setAttr(
186
+ "wcsEnd",
187
+ this._worldTransformer.screenToWorld({ x: position.x + this._ref.width(), y: position.y + this._ref.height() })
188
+ );
189
+ });
190
+
115
191
  this._ref.getSelfRect = () => {
116
192
  return {
117
- x: 0 - arcRadius,
118
- y: 0 - arcRadius,
119
- width: this._ref.width() + 2 * arcRadius,
120
- height: this._ref.height() + 2 * arcRadius,
193
+ x: 0 - ARC_RADIUS,
194
+ y: 0 - ARC_RADIUS,
195
+ width: this._ref.width() + 2 * ARC_RADIUS,
196
+ height: this._ref.height() + 2 * ARC_RADIUS,
121
197
  };
122
198
  };
123
199
 
@@ -164,7 +240,7 @@ export class KonvaCloud implements IMarkupCloud {
164
240
  this._ref.zIndex(zIndex);
165
241
  }
166
242
 
167
- delete() {
243
+ delete(): void {
168
244
  this._ref.destroy();
169
245
  this._ref = null;
170
246
  }
@@ -175,6 +251,10 @@ export class KonvaCloud implements IMarkupCloud {
175
251
 
176
252
  setPosition(x: number, y: number): void {
177
253
  this._ref.position({ x, y });
254
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({ x, y }));
255
+ const rightLowerPoint = { x: x + this._ref.width(), y: y + this._ref.y() };
256
+ const wcsRightLowerPoint = this._worldTransformer.screenToWorld(rightLowerPoint);
257
+ this._ref.setAttr("wcsEnd", wcsRightLowerPoint);
178
258
  }
179
259
 
180
260
  getWidth(): number {
@@ -183,6 +263,10 @@ export class KonvaCloud implements IMarkupCloud {
183
263
 
184
264
  setWidth(w: number): void {
185
265
  this._ref.width(w);
266
+
267
+ const rightLowerPoint = { x: this._ref.x() + w, y: this._ref.y() + this._ref.height() };
268
+ const wcsRightLowerPoint = this._worldTransformer.screenToWorld(rightLowerPoint);
269
+ this._ref.setAttr("wcsEnd", wcsRightLowerPoint);
186
270
  }
187
271
 
188
272
  getHeigth(): number {
@@ -191,6 +275,10 @@ export class KonvaCloud implements IMarkupCloud {
191
275
 
192
276
  setHeight(h: number): void {
193
277
  this._ref.height(h);
278
+
279
+ const rightLowerPoint = { x: this._ref.x() + this._ref.width(), y: this._ref.y() + h };
280
+ const wcsRightLowerPoint = this._worldTransformer.screenToWorld(rightLowerPoint);
281
+ this._ref.setAttr("wcsEnd", wcsRightLowerPoint);
194
282
  }
195
283
 
196
284
  getLineWidth(): number {
@@ -200,4 +288,18 @@ export class KonvaCloud implements IMarkupCloud {
200
288
  setLineWidth(size: number): void {
201
289
  this._ref.strokeWidth(size);
202
290
  }
291
+
292
+ updateScreenCoordinates(): void {
293
+ let screenPositionStart = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsStart"));
294
+ let screenPositionEnd = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsEnd"));
295
+
296
+ let invert = this._ref.getStage().getAbsoluteTransform().copy();
297
+ invert = invert.invert();
298
+ const positionStart = invert.point(screenPositionStart);
299
+ const positionEnd = invert.point(screenPositionEnd);
300
+
301
+ this._ref.position({ x: positionStart.x, y: positionStart.y });
302
+ this._ref.width(Math.abs(positionEnd.x - positionStart.x));
303
+ this._ref.height(Math.abs(positionEnd.y - positionStart.y));
304
+ }
203
305
  }
@@ -1,18 +1,73 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
3
+ // All rights reserved.
4
+ //
5
+ // This software and its documentation and related materials are owned by
6
+ // the Alliance. The software may only be incorporated into application
7
+ // programs owned by members of the Alliance, subject to a signed
8
+ // Membership Agreement and Supplemental Software License Agreement with the
9
+ // Alliance. The structure and organization of this software are the valuable
10
+ // trade secrets of the Alliance and its suppliers. The software is also
11
+ // protected by copyright law and international treaty provisions. Application
12
+ // programs incorporating this software must include the following statement
13
+ // with their copyright notices:
14
+ //
15
+ // This application incorporates Open Design Alliance software pursuant to a
16
+ // license agreement with Open Design Alliance.
17
+ // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
18
+ // All rights reserved.
19
+ //
20
+ // By use of this software, its documentation or related materials, you
21
+ // acknowledge and accept the above terms.
22
+ ///////////////////////////////////////////////////////////////////////////////
23
+
1
24
  import Konva from "konva";
2
25
  import { IMarkupEllipse, IMarkupEllipseParams } from "../IMarkupEllipse";
26
+ import { IWorldTransform } from "../IWorldTransform";
27
+ import { WorldTransform } from "../WorldTransform";
28
+ import * as utils from "../Utils";
3
29
 
4
30
  export class KonvaEllipse implements IMarkupEllipse {
5
31
  private _ref: Konva.Ellipse;
32
+ private _worldTransformer: IWorldTransform;
33
+
34
+ constructor(params: IMarkupEllipseParams, ref = null, worldTransformer = new WorldTransform()) {
35
+ this._worldTransformer = worldTransformer;
6
36
 
7
- constructor(params: IMarkupEllipseParams, ref = null) {
8
37
  if (ref) {
9
38
  this._ref = ref;
39
+
40
+ const wcsPosition = this._ref.getAttr("wcsPosition");
41
+ const radiusX = this._ref.getAttr("wcsRadiusX");
42
+ const radiusY = this._ref.getAttr("wcsRadiusY");
43
+ if (!wcsPosition) {
44
+ this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld({ x: ref.x(), y: ref.y() }));
45
+ }
46
+ if (!radiusX) {
47
+ this._ref.setAttr(
48
+ "wcsRadiusX",
49
+ this._worldTransformer.screenToWorld({ x: ref.x() + ref.radiusX(), y: ref.y() })
50
+ );
51
+ }
52
+ if (!radiusY) {
53
+ this._ref.setAttr(
54
+ "wcsRadiusY",
55
+ this._worldTransformer.screenToWorld({ x: ref.x(), y: ref.y() + ref.radiusY() })
56
+ );
57
+ }
58
+
10
59
  return;
11
60
  }
12
61
 
13
62
  if (!params) params = {};
14
63
  if (!params.position) params.position = { x: 0, y: 0 };
15
- if (!params.radius) params.radius = { x: 25, y: 25 };
64
+ if (params.position2) {
65
+ params.radius.x = utils.getDistanceIn2D(params.position, params.position2);
66
+ if (params.position3) params.radius.y = utils.getDistanceIn2D(params.position, params.position3);
67
+ else params.radius.x = params.radius.y;
68
+ } else {
69
+ if (!params.radius) params.radius = { x: 25, y: 25 };
70
+ }
16
71
 
17
72
  this._ref = new Konva.Ellipse({
18
73
  stroke: params.color ?? "#ff0000",
@@ -28,6 +83,19 @@ export class KonvaEllipse implements IMarkupEllipse {
28
83
  strokeScaleEnabled: false,
29
84
  });
30
85
 
86
+ this._ref.setAttr(
87
+ "wcsPosition",
88
+ this._worldTransformer.screenToWorld({ x: params.position.x, y: params.position.y })
89
+ );
90
+ this._ref.setAttr(
91
+ "wcsRadiusX",
92
+ this._worldTransformer.screenToWorld({ x: this._ref.x() + params.radius.x, y: this._ref.y() })
93
+ );
94
+ this._ref.setAttr(
95
+ "wcsRadiusY",
96
+ this._worldTransformer.screenToWorld({ x: this._ref.x(), y: this._ref.y() + params.radius.y })
97
+ );
98
+
31
99
  this._ref.on("transform", (e) => {
32
100
  const attrs = e.target.attrs;
33
101
 
@@ -60,6 +128,26 @@ export class KonvaEllipse implements IMarkupEllipse {
60
128
  this._ref.scale({ x: 1, y: 1 });
61
129
  });
62
130
 
131
+ this._ref.on("transformend", (e) => {
132
+ const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
133
+ const position = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() });
134
+ this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld(position));
135
+ const radiusX = absoluteTransform.point({ x: this._ref.x() + this._ref.radiusX(), y: this._ref.y() });
136
+ this._ref.setAttr("wcsRadiusX", this._worldTransformer.screenToWorld(radiusX));
137
+ const radiusY = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() + this._ref.radiusY() });
138
+ this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld(radiusY));
139
+ });
140
+
141
+ this._ref.on("dragend", (e) => {
142
+ const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
143
+ const position = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() });
144
+ this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld(position));
145
+ const radiusX = absoluteTransform.point({ x: this._ref.x() + this._ref.radiusX(), y: this._ref.y() });
146
+ this._ref.setAttr("wcsRadiusX", this._worldTransformer.screenToWorld(radiusX));
147
+ const radiusY = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() + this._ref.radiusY() });
148
+ this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld(radiusY));
149
+ });
150
+
63
151
  this._ref.id(this._ref._id.toString());
64
152
  }
65
153
 
@@ -69,6 +157,7 @@ export class KonvaEllipse implements IMarkupEllipse {
69
157
 
70
158
  setPosition(x: number, y: number): void {
71
159
  this._ref.setPosition({ x, y });
160
+ this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld({ x, y }));
72
161
  }
73
162
 
74
163
  getRadiusX(): number {
@@ -77,6 +166,7 @@ export class KonvaEllipse implements IMarkupEllipse {
77
166
 
78
167
  setRadiusX(r: number): void {
79
168
  this._ref.radiusX(r);
169
+ this._ref.setAttr("wcsRadiusX", this._worldTransformer.screenToWorld({ x: this._ref.x() + r, y: this._ref.y() }));
80
170
  }
81
171
 
82
172
  getRadiusY(): number {
@@ -85,6 +175,7 @@ export class KonvaEllipse implements IMarkupEllipse {
85
175
 
86
176
  setRadiusY(r: number): void {
87
177
  this._ref.radiusY(r);
178
+ this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld({ x: this._ref.x(), y: this._ref.y() + r }));
88
179
  }
89
180
 
90
181
  getLineWidth(): number {
@@ -135,8 +226,24 @@ export class KonvaEllipse implements IMarkupEllipse {
135
226
  this._ref.zIndex(zIndex);
136
227
  }
137
228
 
138
- delete() {
229
+ delete(): void {
139
230
  this._ref.destroy();
140
231
  this._ref = null;
141
232
  }
233
+
234
+ updateScreenCoordinates(): void {
235
+ let screenPosition = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsPosition"));
236
+ let radiusX = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsRadiusX"));
237
+ let radiusY = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsRadiusY"));
238
+
239
+ let invert = this._ref.getStage().getAbsoluteTransform().copy();
240
+ invert = invert.invert();
241
+ const position = invert.point({ x: screenPosition.x, y: screenPosition.y });
242
+
243
+ this._ref.position({ x: position.x, y: position.y });
244
+ this._ref.radius({
245
+ x: Math.abs(invert.point(radiusX).x - position.x),
246
+ y: Math.abs(invert.point(radiusY).y - position.y),
247
+ });
248
+ }
142
249
  }