@inweb/markup 26.4.0 → 26.4.2

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 (38) hide show
  1. package/dist/markup.js +561 -126
  2. package/dist/markup.js.map +1 -1
  3. package/dist/markup.min.js +1 -1
  4. package/dist/markup.module.js +672 -138
  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 +4 -4
  9. package/lib/markup/IMarkupImage.d.ts +3 -3
  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 +10 -3
  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/package.json +3 -3
  23. package/src/markup/IMarkupArrow.ts +8 -8
  24. package/src/markup/IMarkupCloud.ts +10 -5
  25. package/src/markup/IMarkupEllipse.ts +4 -4
  26. package/src/markup/IMarkupImage.ts +3 -3
  27. package/src/markup/IMarkupLine.ts +2 -2
  28. package/src/markup/IMarkupObject.ts +5 -0
  29. package/src/markup/IMarkupRectangle.ts +8 -3
  30. package/src/markup/IMarkupText.ts +3 -3
  31. package/src/markup/Konva/KonvaArrow.ts +49 -4
  32. package/src/markup/Konva/KonvaCloud.ts +110 -11
  33. package/src/markup/Konva/KonvaEllipse.ts +102 -2
  34. package/src/markup/Konva/KonvaImage.ts +60 -2
  35. package/src/markup/Konva/KonvaLine.ts +97 -3
  36. package/src/markup/Konva/KonvaMarkup.ts +182 -166
  37. package/src/markup/Konva/KonvaRectangle.ts +103 -4
  38. package/src/markup/Konva/KonvaText.ts +61 -2
@@ -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.position.x - params.position2.x;
57
+ params.height = params.position.y - params.position2.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,7 @@ 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 }));
178
255
  }
179
256
 
180
257
  getWidth(): number {
@@ -183,6 +260,10 @@ export class KonvaCloud implements IMarkupCloud {
183
260
 
184
261
  setWidth(w: number): void {
185
262
  this._ref.width(w);
263
+
264
+ const rightLowerPoint = { x: this._ref.x() + w, y: this._ref.y() + this._ref.height() };
265
+ const wcsRightLowerPoint = this._worldTransformer.screenToWorld(rightLowerPoint);
266
+ this._ref.setAttr("wcsEnd", wcsRightLowerPoint);
186
267
  }
187
268
 
188
269
  getHeigth(): number {
@@ -191,6 +272,10 @@ export class KonvaCloud implements IMarkupCloud {
191
272
 
192
273
  setHeight(h: number): void {
193
274
  this._ref.height(h);
275
+
276
+ const rightLowerPoint = { x: this._ref.x() + this._ref.width(), y: this._ref.y() + h };
277
+ const wcsRightLowerPoint = this._worldTransformer.screenToWorld(rightLowerPoint);
278
+ this._ref.setAttr("wcsEnd", wcsRightLowerPoint);
194
279
  }
195
280
 
196
281
  getLineWidth(): number {
@@ -200,4 +285,18 @@ export class KonvaCloud implements IMarkupCloud {
200
285
  setLineWidth(size: number): void {
201
286
  this._ref.strokeWidth(size);
202
287
  }
288
+
289
+ updateScreenCoordinates(): void {
290
+ let screenPositionStart = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsStart"));
291
+ let screenPositionEnd = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsEnd"));
292
+
293
+ let invert = this._ref.getStage().getAbsoluteTransform().copy();
294
+ invert = invert.invert();
295
+ const positionStart = invert.point(screenPositionStart);
296
+ const positionEnd = invert.point(screenPositionEnd);
297
+
298
+ this._ref.position({ x: positionStart.x, y: positionStart.y });
299
+ this._ref.width(Math.abs(positionEnd.x - positionStart.x));
300
+ this._ref.height(Math.abs(positionEnd.y - positionStart.y));
301
+ }
203
302
  }
@@ -1,12 +1,60 @@
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";
3
28
 
4
29
  export class KonvaEllipse implements IMarkupEllipse {
5
30
  private _ref: Konva.Ellipse;
31
+ private _worldTransformer: IWorldTransform;
32
+
33
+ constructor(params: IMarkupEllipseParams, ref = null, worldTransformer = new WorldTransform()) {
34
+ this._worldTransformer = worldTransformer;
6
35
 
7
- constructor(params: IMarkupEllipseParams, ref = null) {
8
36
  if (ref) {
9
37
  this._ref = ref;
38
+
39
+ const wcsPosition = this._ref.getAttr("wcsPosition");
40
+ const radiusX = this._ref.getAttr("wcsRadiusX");
41
+ const radiusY = this._ref.getAttr("wcsRadiusY");
42
+ if (!wcsPosition) {
43
+ this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld({ x: ref.x(), y: ref.y() }));
44
+ }
45
+ if (!radiusX) {
46
+ this._ref.setAttr(
47
+ "wcsRadiusX",
48
+ this._worldTransformer.screenToWorld({ x: ref.x() + ref.radiusX(), y: ref.y() })
49
+ );
50
+ }
51
+ if (!radiusY) {
52
+ this._ref.setAttr(
53
+ "wcsRadiusY",
54
+ this._worldTransformer.screenToWorld({ x: ref.x(), y: ref.y() + ref.radiusY() })
55
+ );
56
+ }
57
+
10
58
  return;
11
59
  }
12
60
 
@@ -28,6 +76,19 @@ export class KonvaEllipse implements IMarkupEllipse {
28
76
  strokeScaleEnabled: false,
29
77
  });
30
78
 
79
+ this._ref.setAttr(
80
+ "wcsPosition",
81
+ this._worldTransformer.screenToWorld({ x: params.position.x, y: params.position.y })
82
+ );
83
+ this._ref.setAttr(
84
+ "wcsRadiusX",
85
+ this._worldTransformer.screenToWorld({ x: this._ref.x() + params.radius.x, y: this._ref.y() })
86
+ );
87
+ this._ref.setAttr(
88
+ "wcsRadiusY",
89
+ this._worldTransformer.screenToWorld({ x: this._ref.x(), y: this._ref.y() + params.radius.y })
90
+ );
91
+
31
92
  this._ref.on("transform", (e) => {
32
93
  const attrs = e.target.attrs;
33
94
 
@@ -60,6 +121,26 @@ export class KonvaEllipse implements IMarkupEllipse {
60
121
  this._ref.scale({ x: 1, y: 1 });
61
122
  });
62
123
 
124
+ this._ref.on("transformend", (e) => {
125
+ const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
126
+ const position = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() });
127
+ this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld(position));
128
+ const radiusX = absoluteTransform.point({ x: this._ref.x() + this._ref.radiusX(), y: this._ref.y() });
129
+ this._ref.setAttr("wcsRadiusX", this._worldTransformer.screenToWorld(radiusX));
130
+ const radiusY = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() + this._ref.radiusY() });
131
+ this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld(radiusY));
132
+ });
133
+
134
+ this._ref.on("dragend", (e) => {
135
+ const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
136
+ const position = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() });
137
+ this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld(position));
138
+ const radiusX = absoluteTransform.point({ x: this._ref.x() + this._ref.radiusX(), y: this._ref.y() });
139
+ this._ref.setAttr("wcsRadiusX", this._worldTransformer.screenToWorld(radiusX));
140
+ const radiusY = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() + this._ref.radiusY() });
141
+ this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld(radiusY));
142
+ });
143
+
63
144
  this._ref.id(this._ref._id.toString());
64
145
  }
65
146
 
@@ -69,6 +150,7 @@ export class KonvaEllipse implements IMarkupEllipse {
69
150
 
70
151
  setPosition(x: number, y: number): void {
71
152
  this._ref.setPosition({ x, y });
153
+ this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld({ x, y }));
72
154
  }
73
155
 
74
156
  getRadiusX(): number {
@@ -77,6 +159,7 @@ export class KonvaEllipse implements IMarkupEllipse {
77
159
 
78
160
  setRadiusX(r: number): void {
79
161
  this._ref.radiusX(r);
162
+ this._ref.setAttr("wcsRadiusX", this._worldTransformer.screenToWorld({ x: this._ref.x() + r, y: this._ref.y() }));
80
163
  }
81
164
 
82
165
  getRadiusY(): number {
@@ -85,6 +168,7 @@ export class KonvaEllipse implements IMarkupEllipse {
85
168
 
86
169
  setRadiusY(r: number): void {
87
170
  this._ref.radiusY(r);
171
+ this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld({ x: this._ref.x(), y: this._ref.y() + r }));
88
172
  }
89
173
 
90
174
  getLineWidth(): number {
@@ -135,8 +219,24 @@ export class KonvaEllipse implements IMarkupEllipse {
135
219
  this._ref.zIndex(zIndex);
136
220
  }
137
221
 
138
- delete() {
222
+ delete(): void {
139
223
  this._ref.destroy();
140
224
  this._ref = null;
141
225
  }
226
+
227
+ updateScreenCoordinates(): void {
228
+ let screenPosition = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsPosition"));
229
+ let radiusX = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsRadiusX"));
230
+ let radiusY = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsRadiusY"));
231
+
232
+ let invert = this._ref.getStage().getAbsoluteTransform().copy();
233
+ invert = invert.invert();
234
+ const position = invert.point({ x: screenPosition.x, y: screenPosition.y });
235
+
236
+ this._ref.position({ x: position.x, y: position.y });
237
+ this._ref.radius({
238
+ x: Math.abs(invert.point(radiusX).x - position.x),
239
+ y: Math.abs(invert.point(radiusY).y - position.y),
240
+ });
241
+ }
142
242
  }
@@ -1,5 +1,30 @@
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 { IMarkupImage, IMarkupImageParams } from "../IMarkupImage";
26
+ import { IWorldTransform } from "../IWorldTransform";
27
+ import { WorldTransform } from "../WorldTransform";
3
28
 
4
29
  export class KonvaImage implements IMarkupImage {
5
30
  private _ref: Konva.Image;
@@ -9,8 +34,11 @@ export class KonvaImage implements IMarkupImage {
9
34
  private readonly BASE64_HEADER_START = "data:image/";
10
35
  private readonly BASE64_NOT_FOUND =
11
36
  "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAADsAAAA7AF5KHG9AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAmhJREFUWIXtlr9rVEEQxz+H8RQUJIdeIopYm0vkCg0GBBtbG1NF7Kxt7dR/IGIw/uhTaBNLERURg2kCEUyCYCPi70b0InjGS57FzOZN3r19d+9HJIVfWO52dma/s7Mz8xa2KAaBCWAR+AkECWOmSOIdwC1gtQOpHc+NfQ8wClQ8+1d0vcdH/lQ3bSIRGAZ2pTjAqNovANXIWlXlAXA2zvi2Ln4AjqYgtagYEutENSLvjRoOImFv5iB32Ae8UrLXwFBk3h9ndF0VJnKSO9gTu3yKu5Z1LKnS8YIcABgw5Ks692JZFXcXRJ46Aq6kikCnHNi/mQ50WwVtfaIoBzL3gRk2drSscJ2wrc4VvUoe2wn/41/iBfoVLRnBGnDSY3AAKacy8AmYR+o7K1zCl6wgrgpOAc/MuhvfgMuk+1JGHQgSBcAloKXy78AjYBppJk5/noTulseBMZ23iD/piHFkEdgTQzKk+5wHjmHC3cmBg0BD5xcSTrFXyQPgIWFtDwMvab+2N8DpbhyY1v/3E8gdDgNfVX9SCVZ0/gW4B0wB71S2BpxLcuCM/jaQSHSDEeAX4VMuAG4gTzyHbcAVXXO6GxxwIX+vvxe7JHcYQ07nHqklj96UIW/YhSWzMKcep8VVtf8B1Dw6h4DfhB+sdbgn2R+gnoEc5NR3dZ+3QJ9H74HqXLPCGlJyTfI9y3YCs0owq3OLOpKkLeBI1HhSDT/mdKIPiUCARMTlQx34TMLjtww8IczmO8AJ/N/2JNSQXAiQ671JePePge0+wzJSQq4FFzlaenIvucUAkiQLhC/mLGNZ9xgn5s63BP4CCk0QDtm4BhoAAAAASUVORK5CYII=";
37
+ private _worldTransformer: IWorldTransform;
38
+
39
+ constructor(params: IMarkupImageParams, ref = null, worldTransformer = new WorldTransform()) {
40
+ this._worldTransformer = worldTransformer;
12
41
 
13
- constructor(params: IMarkupImageParams, ref = null) {
14
42
  if (ref) {
15
43
  if (!ref.src || !ref.src.startsWith(this.BASE64_HEADER_START)) ref.src = this.BASE64_NOT_FOUND;
16
44
  if (ref.height() <= this.EPSILON) ref.height(32);
@@ -23,6 +51,11 @@ export class KonvaImage implements IMarkupImage {
23
51
  ? 1
24
52
  : this._ref.height() / this._ref.width();
25
53
 
54
+ const wcsStart = this._ref.getAttr("wcsStart");
55
+ if (!wcsStart) {
56
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({ x: ref.x(), y: ref.y() }));
57
+ }
58
+
26
59
  return;
27
60
  }
28
61
 
@@ -78,6 +111,8 @@ export class KonvaImage implements IMarkupImage {
78
111
  draggable: true,
79
112
  });
80
113
 
114
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({ x: params.position.x, y: params.position.y }));
115
+
81
116
  this._ref.on("transform", (e) => {
82
117
  const attrs = e.target.attrs;
83
118
 
@@ -111,6 +146,18 @@ export class KonvaImage implements IMarkupImage {
111
146
  this._ref.scale({ x: 1, y: 1 });
112
147
  });
113
148
 
149
+ this._ref.on("transformend", (e) => {
150
+ const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
151
+ const position = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() });
152
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
153
+ });
154
+
155
+ this._ref.on("dragend", (e) => {
156
+ const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
157
+ const position = absoluteTransform.point({ x: this._ref.x(), y: this._ref.y() });
158
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
159
+ });
160
+
114
161
  this._ref.id(this._ref._id.toString());
115
162
  }
116
163
 
@@ -172,7 +219,7 @@ export class KonvaImage implements IMarkupImage {
172
219
  this._ref.zIndex(zIndex);
173
220
  }
174
221
 
175
- delete() {
222
+ delete(): void {
176
223
  this._ref.destroy();
177
224
  this._ref = null;
178
225
  }
@@ -183,5 +230,16 @@ export class KonvaImage implements IMarkupImage {
183
230
 
184
231
  setPosition(x: number, y: number): void {
185
232
  this._ref.setPosition({ x, y });
233
+ this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({ x, y }));
234
+ }
235
+
236
+ updateScreenCoordinates(): void {
237
+ let screenPositionStart = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsStart"));
238
+
239
+ let invert = this._ref.getStage().getAbsoluteTransform().copy();
240
+ invert = invert.invert();
241
+ const positionStart = invert.point(screenPositionStart);
242
+
243
+ this._ref.position({ x: positionStart.x, y: positionStart.y });
186
244
  }
187
245
  }