@nasser-sw/fabric 7.0.1-beta3 → 7.0.1-beta4

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 (105) hide show
  1. package/0 +0 -0
  2. package/dist/index.js +323 -155
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.min.js +1 -1
  5. package/dist/index.min.js.map +1 -1
  6. package/dist/index.min.mjs +1 -1
  7. package/dist/index.min.mjs.map +1 -1
  8. package/dist/index.mjs +323 -155
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/index.node.cjs +323 -155
  11. package/dist/index.node.cjs.map +1 -1
  12. package/dist/index.node.mjs +323 -155
  13. package/dist/index.node.mjs.map +1 -1
  14. package/dist/package.json.min.mjs +1 -1
  15. package/dist/package.json.mjs +1 -1
  16. package/dist/src/shapes/Line.d.ts +31 -86
  17. package/dist/src/shapes/Line.d.ts.map +1 -1
  18. package/dist/src/shapes/Line.min.mjs +1 -1
  19. package/dist/src/shapes/Line.min.mjs.map +1 -1
  20. package/dist/src/shapes/Line.mjs +323 -154
  21. package/dist/src/shapes/Line.mjs.map +1 -1
  22. package/dist-extensions/src/shapes/CustomLine.d.ts +10 -0
  23. package/dist-extensions/src/shapes/CustomLine.d.ts.map +1 -0
  24. package/dist-extensions/src/shapes/Line.d.ts +31 -86
  25. package/dist-extensions/src/shapes/Line.d.ts.map +1 -1
  26. package/fabric-test-editor.html +157 -8
  27. package/fabric-test2.html +513 -0
  28. package/fabric.ts +182 -182
  29. package/package.json +1 -1
  30. package/src/shapes/Line.ts +372 -158
  31. package/debug/konva/CHANGELOG.md +0 -1474
  32. package/debug/konva/LICENSE +0 -22
  33. package/debug/konva/README.md +0 -205
  34. package/debug/konva/gulpfile.mjs +0 -110
  35. package/debug/konva/package.json +0 -139
  36. package/debug/konva/release.sh +0 -65
  37. package/debug/konva/resources/doc-includes/ContainerParams.txt +0 -6
  38. package/debug/konva/resources/doc-includes/NodeParams.txt +0 -20
  39. package/debug/konva/resources/doc-includes/ShapeParams.txt +0 -53
  40. package/debug/konva/resources/jsdoc.conf.json +0 -28
  41. package/debug/konva/rollup.config.mjs +0 -32
  42. package/debug/konva/src/Animation.ts +0 -237
  43. package/debug/konva/src/BezierFunctions.ts +0 -826
  44. package/debug/konva/src/Canvas.ts +0 -193
  45. package/debug/konva/src/Container.ts +0 -649
  46. package/debug/konva/src/Context.ts +0 -1017
  47. package/debug/konva/src/Core.ts +0 -5
  48. package/debug/konva/src/DragAndDrop.ts +0 -173
  49. package/debug/konva/src/Factory.ts +0 -246
  50. package/debug/konva/src/FastLayer.ts +0 -29
  51. package/debug/konva/src/Global.ts +0 -210
  52. package/debug/konva/src/Group.ts +0 -31
  53. package/debug/konva/src/Layer.ts +0 -546
  54. package/debug/konva/src/Node.ts +0 -3477
  55. package/debug/konva/src/PointerEvents.ts +0 -67
  56. package/debug/konva/src/Shape.ts +0 -2081
  57. package/debug/konva/src/Stage.ts +0 -1000
  58. package/debug/konva/src/Tween.ts +0 -811
  59. package/debug/konva/src/Util.ts +0 -1123
  60. package/debug/konva/src/Validators.ts +0 -210
  61. package/debug/konva/src/_CoreInternals.ts +0 -85
  62. package/debug/konva/src/_FullInternals.ts +0 -171
  63. package/debug/konva/src/canvas-backend.ts +0 -36
  64. package/debug/konva/src/filters/Blur.ts +0 -388
  65. package/debug/konva/src/filters/Brighten.ts +0 -48
  66. package/debug/konva/src/filters/Brightness.ts +0 -30
  67. package/debug/konva/src/filters/Contrast.ts +0 -75
  68. package/debug/konva/src/filters/Emboss.ts +0 -207
  69. package/debug/konva/src/filters/Enhance.ts +0 -154
  70. package/debug/konva/src/filters/Grayscale.ts +0 -25
  71. package/debug/konva/src/filters/HSL.ts +0 -108
  72. package/debug/konva/src/filters/HSV.ts +0 -106
  73. package/debug/konva/src/filters/Invert.ts +0 -23
  74. package/debug/konva/src/filters/Kaleidoscope.ts +0 -274
  75. package/debug/konva/src/filters/Mask.ts +0 -220
  76. package/debug/konva/src/filters/Noise.ts +0 -44
  77. package/debug/konva/src/filters/Pixelate.ts +0 -107
  78. package/debug/konva/src/filters/Posterize.ts +0 -46
  79. package/debug/konva/src/filters/RGB.ts +0 -82
  80. package/debug/konva/src/filters/RGBA.ts +0 -103
  81. package/debug/konva/src/filters/Sepia.ts +0 -27
  82. package/debug/konva/src/filters/Solarize.ts +0 -29
  83. package/debug/konva/src/filters/Threshold.ts +0 -44
  84. package/debug/konva/src/index.ts +0 -3
  85. package/debug/konva/src/shapes/Arc.ts +0 -176
  86. package/debug/konva/src/shapes/Arrow.ts +0 -231
  87. package/debug/konva/src/shapes/Circle.ts +0 -76
  88. package/debug/konva/src/shapes/Ellipse.ts +0 -121
  89. package/debug/konva/src/shapes/Image.ts +0 -319
  90. package/debug/konva/src/shapes/Label.ts +0 -386
  91. package/debug/konva/src/shapes/Line.ts +0 -364
  92. package/debug/konva/src/shapes/Path.ts +0 -1013
  93. package/debug/konva/src/shapes/Rect.ts +0 -79
  94. package/debug/konva/src/shapes/RegularPolygon.ts +0 -167
  95. package/debug/konva/src/shapes/Ring.ts +0 -94
  96. package/debug/konva/src/shapes/Sprite.ts +0 -370
  97. package/debug/konva/src/shapes/Star.ts +0 -125
  98. package/debug/konva/src/shapes/Text.ts +0 -1065
  99. package/debug/konva/src/shapes/TextPath.ts +0 -583
  100. package/debug/konva/src/shapes/Transformer.ts +0 -1889
  101. package/debug/konva/src/shapes/Wedge.ts +0 -129
  102. package/debug/konva/src/skia-backend.ts +0 -35
  103. package/debug/konva/src/types.ts +0 -84
  104. package/debug/konva/tsconfig.json +0 -31
  105. package/debug/konva/tsconfig.test.json +0 -7
@@ -1,1889 +0,0 @@
1
- import { Util, Transform } from '../Util.ts';
2
- import { Factory } from '../Factory.ts';
3
- import { Node } from '../Node.ts';
4
- import { Shape } from '../Shape.ts';
5
- import { Rect } from './Rect.ts';
6
- import { Group } from '../Group.ts';
7
- import type { ContainerConfig } from '../Container.ts';
8
- import { Konva } from '../Global.ts';
9
- import { getBooleanValidator, getNumberValidator } from '../Validators.ts';
10
- import { _registerNode } from '../Global.ts';
11
-
12
- import type { GetSet, IRect, Vector2d } from '../types.ts';
13
-
14
- export interface Box extends IRect {
15
- rotation: number;
16
- }
17
-
18
- export interface TransformerConfig extends ContainerConfig {
19
- resizeEnabled?: boolean;
20
- rotateEnabled?: boolean;
21
- rotateLineVisible?: boolean;
22
- rotationSnaps?: Array<number>;
23
- rotationSnapTolerance?: number;
24
- rotateAnchorOffset?: number;
25
- rotateAnchorCursor?: string;
26
- borderEnabled?: boolean;
27
- borderStroke?: string;
28
- borderStrokeWidth?: number;
29
- borderDash?: Array<number>;
30
- anchorFill?: string;
31
- anchorStroke?: string;
32
- anchorStrokeWidth?: number;
33
- anchorSize?: number;
34
- anchorCornerRadius?: number;
35
- keepRatio?: boolean;
36
- shiftBehavior?: string;
37
- centeredScaling?: boolean;
38
- enabledAnchors?: Array<string>;
39
- flipEnabled?: boolean;
40
- node?: Rect;
41
- ignoreStroke?: boolean;
42
- boundBoxFunc?: (oldBox: Box, newBox: Box) => Box;
43
- useSingleNodeRotation?: boolean;
44
- shouldOverdrawWholeArea?: boolean;
45
- anchorDragBoundFunc?: (
46
- oldPos: Vector2d,
47
- newPos: Vector2d,
48
- evt: any
49
- ) => Vector2d;
50
- anchorStyleFunc?: (anchor: Rect) => void;
51
- }
52
-
53
- const EVENTS_NAME = 'tr-konva';
54
-
55
- const ATTR_CHANGE_LIST = [
56
- 'resizeEnabledChange',
57
- 'rotateAnchorOffsetChange',
58
- 'rotateEnabledChange',
59
- 'enabledAnchorsChange',
60
- 'anchorSizeChange',
61
- 'borderEnabledChange',
62
- 'borderStrokeChange',
63
- 'borderStrokeWidthChange',
64
- 'borderDashChange',
65
- 'anchorStrokeChange',
66
- 'anchorStrokeWidthChange',
67
- 'anchorFillChange',
68
- 'anchorCornerRadiusChange',
69
- 'ignoreStrokeChange',
70
- 'anchorStyleFuncChange',
71
- ]
72
- .map((e) => e + `.${EVENTS_NAME}`)
73
- .join(' ');
74
-
75
- const NODES_RECT = 'nodesRect';
76
-
77
- const TRANSFORM_CHANGE_STR = [
78
- 'widthChange',
79
- 'heightChange',
80
- 'scaleXChange',
81
- 'scaleYChange',
82
- 'skewXChange',
83
- 'skewYChange',
84
- 'rotationChange',
85
- 'offsetXChange',
86
- 'offsetYChange',
87
- 'transformsEnabledChange',
88
- 'strokeWidthChange',
89
- 'draggableChange',
90
- ];
91
-
92
- const ANGLES = {
93
- 'top-left': -45,
94
- 'top-center': 0,
95
- 'top-right': 45,
96
- 'middle-right': -90,
97
- 'middle-left': 90,
98
- 'bottom-left': -135,
99
- 'bottom-center': 180,
100
- 'bottom-right': 135,
101
- };
102
-
103
- const TOUCH_DEVICE = 'ontouchstart' in Konva._global;
104
-
105
- function getCursor(anchorName, rad, rotateCursor) {
106
- if (anchorName === 'rotater') {
107
- return rotateCursor;
108
- }
109
-
110
- rad += Util.degToRad(ANGLES[anchorName] || 0);
111
- const angle = ((Util.radToDeg(rad) % 360) + 360) % 360;
112
-
113
- if (Util._inRange(angle, 315 + 22.5, 360) || Util._inRange(angle, 0, 22.5)) {
114
- // TOP
115
- return 'ns-resize';
116
- } else if (Util._inRange(angle, 45 - 22.5, 45 + 22.5)) {
117
- // TOP - RIGHT
118
- return 'nesw-resize';
119
- } else if (Util._inRange(angle, 90 - 22.5, 90 + 22.5)) {
120
- // RIGHT
121
- return 'ew-resize';
122
- } else if (Util._inRange(angle, 135 - 22.5, 135 + 22.5)) {
123
- // BOTTOM - RIGHT
124
- return 'nwse-resize';
125
- } else if (Util._inRange(angle, 180 - 22.5, 180 + 22.5)) {
126
- // BOTTOM
127
- return 'ns-resize';
128
- } else if (Util._inRange(angle, 225 - 22.5, 225 + 22.5)) {
129
- // BOTTOM - LEFT
130
- return 'nesw-resize';
131
- } else if (Util._inRange(angle, 270 - 22.5, 270 + 22.5)) {
132
- // RIGHT
133
- return 'ew-resize';
134
- } else if (Util._inRange(angle, 315 - 22.5, 315 + 22.5)) {
135
- // BOTTOM - RIGHT
136
- return 'nwse-resize';
137
- } else {
138
- // how can we can there?
139
- Util.error('Transformer has unknown angle for cursor detection: ' + angle);
140
- return 'pointer';
141
- }
142
- }
143
-
144
- const ANCHORS_NAMES = [
145
- 'top-left',
146
- 'top-center',
147
- 'top-right',
148
- 'middle-right',
149
- 'middle-left',
150
- 'bottom-left',
151
- 'bottom-center',
152
- 'bottom-right',
153
- ];
154
-
155
- const MAX_SAFE_INTEGER = 100000000;
156
-
157
- function getCenter(shape: Box) {
158
- return {
159
- x:
160
- shape.x +
161
- (shape.width / 2) * Math.cos(shape.rotation) +
162
- (shape.height / 2) * Math.sin(-shape.rotation),
163
- y:
164
- shape.y +
165
- (shape.height / 2) * Math.cos(shape.rotation) +
166
- (shape.width / 2) * Math.sin(shape.rotation),
167
- };
168
- }
169
-
170
- function rotateAroundPoint(shape: Box, angleRad: number, point: Vector2d) {
171
- const x =
172
- point.x +
173
- (shape.x - point.x) * Math.cos(angleRad) -
174
- (shape.y - point.y) * Math.sin(angleRad);
175
- const y =
176
- point.y +
177
- (shape.x - point.x) * Math.sin(angleRad) +
178
- (shape.y - point.y) * Math.cos(angleRad);
179
- return {
180
- ...shape,
181
- rotation: shape.rotation + angleRad,
182
- x,
183
- y,
184
- };
185
- }
186
-
187
- function rotateAroundCenter(shape: Box, deltaRad: number) {
188
- const center = getCenter(shape);
189
- return rotateAroundPoint(shape, deltaRad, center);
190
- }
191
-
192
- function getSnap(snaps: Array<number>, newRotationRad: number, tol: number) {
193
- let snapped = newRotationRad;
194
- for (let i = 0; i < snaps.length; i++) {
195
- const angle = Konva.getAngle(snaps[i]);
196
-
197
- const absDiff = Math.abs(angle - newRotationRad) % (Math.PI * 2);
198
- const dif = Math.min(absDiff, Math.PI * 2 - absDiff);
199
-
200
- if (dif < tol) {
201
- snapped = angle;
202
- }
203
- }
204
- return snapped;
205
- }
206
-
207
- let activeTransformersCount = 0;
208
- /**
209
- * Transformer constructor. Transformer is a special type of group that allow you transform Konva
210
- * primitives and shapes. Transforming tool is not changing `width` and `height` properties of nodes
211
- * when you resize them. Instead it changes `scaleX` and `scaleY` properties.
212
- * @constructor
213
- * @memberof Konva
214
- * @param {Object} config
215
- * @param {Boolean} [config.resizeEnabled] Default is true
216
- * @param {Boolean} [config.rotateEnabled] Default is true
217
- * @param {Boolean} [config.rotateLineVisible] Default is true
218
- * @param {Array} [config.rotationSnaps] Array of angles for rotation snaps. Default is []
219
- * @param {Number} [config.rotationSnapTolerance] Snapping tolerance. If closer than this it will snap. Default is 5
220
- * @param {Number} [config.rotateAnchorOffset] Default is 50
221
- * @param {String} [config.rotateAnchorCursor] Default is crosshair
222
- * @param {Number} [config.padding] Default is 0
223
- * @param {Boolean} [config.borderEnabled] Should we draw border? Default is true
224
- * @param {String} [config.borderStroke] Border stroke color
225
- * @param {Number} [config.borderStrokeWidth] Border stroke size
226
- * @param {Array} [config.borderDash] Array for border dash.
227
- * @param {String} [config.anchorFill] Anchor fill color
228
- * @param {String} [config.anchorStroke] Anchor stroke color
229
- * @param {String} [config.anchorCornerRadius] Anchor corner radius
230
- * @param {Number} [config.anchorStrokeWidth] Anchor stroke size
231
- * @param {Number} [config.anchorSize] Default is 10
232
- * @param {Boolean} [config.keepRatio] Should we keep ratio when we are moving edges? Default is true
233
- * @param {String} [config.shiftBehavior] How does transformer react on shift key press when we are moving edges? Default is 'default'
234
- * @param {Boolean} [config.centeredScaling] Should we resize relative to node's center? Default is false
235
- * @param {Array} [config.enabledAnchors] Array of names of enabled handles
236
- * @param {Boolean} [config.flipEnabled] Can we flip/mirror shape on transform?. True by default
237
- * @param {Function} [config.boundBoxFunc] Bounding box function
238
- * @param {Function} [config.ignoreStroke] Should we ignore stroke size? Default is false
239
- * @param {Boolean} [config.useSingleNodeRotation] When just one node attached, should we use its rotation for transformer?
240
- * @param {Boolean} [config.shouldOverdrawWholeArea] Should we fill whole transformer area with fake transparent shape to enable dragging from empty spaces?
241
- * @example
242
- * var transformer = new Konva.Transformer({
243
- * nodes: [rectangle],
244
- * rotateAnchorOffset: 60,
245
- * enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right']
246
- * });
247
- * layer.add(transformer);
248
- */
249
- export class Transformer extends Group {
250
- _nodes: Array<Node>;
251
- _movingAnchorName: string | null = null;
252
- _transforming = false;
253
- _anchorDragOffset: Vector2d;
254
- sin: number;
255
- cos: number;
256
- _cursorChange: boolean;
257
-
258
- static isTransforming = () => {
259
- return activeTransformersCount > 0;
260
- };
261
-
262
- constructor(config?: TransformerConfig) {
263
- // call super constructor
264
- super(config);
265
- this._createElements();
266
-
267
- // bindings
268
- this._handleMouseMove = this._handleMouseMove.bind(this);
269
- this._handleMouseUp = this._handleMouseUp.bind(this);
270
- this.update = this.update.bind(this);
271
-
272
- // update transformer data for certain attr changes
273
- this.on(ATTR_CHANGE_LIST, this.update);
274
-
275
- if (this.getNode()) {
276
- this.update();
277
- }
278
- }
279
- /**
280
- * alias to `tr.nodes([shape])`/ This method is deprecated and will be removed soon.
281
- * @method
282
- * @name Konva.Transformer#attachTo
283
- * @returns {Konva.Transformer}
284
- * @example
285
- * transformer.attachTo(shape);
286
- */
287
- attachTo(node: Node) {
288
- this.setNode(node);
289
- return this;
290
- }
291
- setNode(node: Node) {
292
- Util.warn(
293
- 'tr.setNode(shape), tr.node(shape) and tr.attachTo(shape) methods are deprecated. Please use tr.nodes(nodesArray) instead.'
294
- );
295
- return this.setNodes([node]);
296
- }
297
- getNode() {
298
- return this._nodes && this._nodes[0];
299
- }
300
-
301
- _getEventNamespace() {
302
- return EVENTS_NAME + this._id;
303
- }
304
-
305
- setNodes(nodes: Array<Node> = []) {
306
- if (this._nodes && this._nodes.length) {
307
- this.detach();
308
- }
309
-
310
- const filteredNodes = nodes.filter((node) => {
311
- // check if ancestor of the transformer
312
- if (node.isAncestorOf(this)) {
313
- Util.error(
314
- 'Konva.Transformer cannot be an a child of the node you are trying to attach'
315
- );
316
- return false;
317
- }
318
-
319
- return true;
320
- });
321
-
322
- this._nodes = nodes = filteredNodes;
323
- if (nodes.length === 1 && this.useSingleNodeRotation()) {
324
- this.rotation(nodes[0].getAbsoluteRotation());
325
- } else {
326
- this.rotation(0);
327
- }
328
- this._nodes.forEach((node) => {
329
- const onChange = () => {
330
- if (this.nodes().length === 1 && this.useSingleNodeRotation()) {
331
- this.rotation(this.nodes()[0].getAbsoluteRotation());
332
- }
333
-
334
- this._resetTransformCache();
335
- if (!this._transforming && !this.isDragging()) {
336
- this.update();
337
- }
338
- };
339
- if (node._attrsAffectingSize.length) {
340
- const additionalEvents = node._attrsAffectingSize
341
- .map((prop) => prop + 'Change.' + this._getEventNamespace())
342
- .join(' ');
343
- node.on(additionalEvents, onChange);
344
- }
345
- node.on(
346
- TRANSFORM_CHANGE_STR.map(
347
- (e) => e + `.${this._getEventNamespace()}`
348
- ).join(' '),
349
- onChange
350
- );
351
- node.on(`absoluteTransformChange.${this._getEventNamespace()}`, onChange);
352
- this._proxyDrag(node);
353
- });
354
- this._resetTransformCache();
355
- // we may need it if we set node in initial props
356
- // so elements are not defined yet
357
- const elementsCreated = !!this.findOne('.top-left');
358
- if (elementsCreated) {
359
- this.update();
360
- }
361
- return this;
362
- }
363
-
364
- _proxyDrag(node: Node) {
365
- let lastPos;
366
- node.on(`dragstart.${this._getEventNamespace()}`, (e) => {
367
- lastPos = node.getAbsolutePosition();
368
- // actual dragging of Transformer doesn't make sense
369
- // but we need to make sure it also has all drag events
370
- if (!this.isDragging() && node !== this.findOne('.back')) {
371
- this.startDrag(e, false);
372
- }
373
- });
374
- node.on(`dragmove.${this._getEventNamespace()}`, (e) => {
375
- if (!lastPos) {
376
- return;
377
- }
378
- const abs = node.getAbsolutePosition();
379
- const dx = abs.x - lastPos.x;
380
- const dy = abs.y - lastPos.y;
381
- this.nodes().forEach((otherNode) => {
382
- if (otherNode === node) {
383
- return;
384
- }
385
- if (otherNode.isDragging()) {
386
- return;
387
- }
388
- const otherAbs = otherNode.getAbsolutePosition();
389
- otherNode.setAbsolutePosition({
390
- x: otherAbs.x + dx,
391
- y: otherAbs.y + dy,
392
- });
393
- otherNode.startDrag(e);
394
- });
395
- lastPos = null;
396
- });
397
- }
398
-
399
- getNodes() {
400
- return this._nodes || [];
401
- }
402
- /**
403
- * return the name of current active anchor
404
- * @method
405
- * @name Konva.Transformer#getActiveAnchor
406
- * @returns {String | Null}
407
- * @example
408
- * transformer.getActiveAnchor();
409
- */
410
- getActiveAnchor() {
411
- return this._movingAnchorName;
412
- }
413
- /**
414
- * detach transformer from an attached node
415
- * @method
416
- * @name Konva.Transformer#detach
417
- * @returns {Konva.Transformer}
418
- * @example
419
- * transformer.detach();
420
- */
421
- detach() {
422
- // remove events
423
- if (this._nodes) {
424
- this._nodes.forEach((node) => {
425
- node.off('.' + this._getEventNamespace());
426
- });
427
- }
428
- this._nodes = [];
429
- this._resetTransformCache();
430
- }
431
- /**
432
- * bind events to the Transformer. You can use events: `transform`, `transformstart`, `transformend`, `dragstart`, `dragmove`, `dragend`
433
- * @method
434
- * @name Konva.Transformer#on
435
- * @param {String} evtStr e.g. 'transform'
436
- * @param {Function} handler The handler function. The first argument of that function is event object. Event object has `target` as main target of the event, `currentTarget` as current node listener and `evt` as native browser event.
437
- * @returns {Konva.Transformer}
438
- * @example
439
- * // add click listener
440
- * tr.on('transformstart', function() {
441
- * console.log('transform started');
442
- * });
443
- */
444
- _resetTransformCache() {
445
- this._clearCache(NODES_RECT);
446
- this._clearCache('transform');
447
- this._clearSelfAndDescendantCache('absoluteTransform');
448
- }
449
- _getNodeRect() {
450
- return this._getCache(NODES_RECT, this.__getNodeRect);
451
- }
452
-
453
- // return absolute rotated bounding rectangle
454
- __getNodeShape(node: Node, rot = this.rotation(), relative?: Node) {
455
- const rect = node.getClientRect({
456
- skipTransform: true,
457
- skipShadow: true,
458
- skipStroke: this.ignoreStroke(),
459
- });
460
-
461
- const absScale = node.getAbsoluteScale(relative);
462
- const absPos = node.getAbsolutePosition(relative);
463
-
464
- const dx = rect.x * absScale.x - node.offsetX() * absScale.x;
465
- const dy = rect.y * absScale.y - node.offsetY() * absScale.y;
466
-
467
- const rotation =
468
- (Konva.getAngle(node.getAbsoluteRotation()) + Math.PI * 2) %
469
- (Math.PI * 2);
470
-
471
- const box = {
472
- x: absPos.x + dx * Math.cos(rotation) + dy * Math.sin(-rotation),
473
- y: absPos.y + dy * Math.cos(rotation) + dx * Math.sin(rotation),
474
- width: rect.width * absScale.x,
475
- height: rect.height * absScale.y,
476
- rotation: rotation,
477
- };
478
- return rotateAroundPoint(box, -Konva.getAngle(rot), {
479
- x: 0,
480
- y: 0,
481
- });
482
- }
483
- // returns box + rotation of all shapes
484
- __getNodeRect() {
485
- const node = this.getNode();
486
- if (!node) {
487
- return {
488
- x: -MAX_SAFE_INTEGER,
489
- y: -MAX_SAFE_INTEGER,
490
- width: 0,
491
- height: 0,
492
- rotation: 0,
493
- };
494
- }
495
-
496
- const totalPoints: Vector2d[] = [];
497
- this.nodes().map((node) => {
498
- const box = node.getClientRect({
499
- skipTransform: true,
500
- skipShadow: true,
501
- skipStroke: this.ignoreStroke(),
502
- });
503
- const points = [
504
- { x: box.x, y: box.y },
505
- { x: box.x + box.width, y: box.y },
506
- { x: box.x + box.width, y: box.y + box.height },
507
- { x: box.x, y: box.y + box.height },
508
- ];
509
- const trans = node.getAbsoluteTransform();
510
- points.forEach(function (point) {
511
- const transformed = trans.point(point);
512
- totalPoints.push(transformed);
513
- });
514
- });
515
-
516
- const tr = new Transform();
517
- tr.rotate(-Konva.getAngle(this.rotation()));
518
-
519
- let minX: number = Infinity,
520
- minY: number = Infinity,
521
- maxX: number = -Infinity,
522
- maxY: number = -Infinity;
523
- totalPoints.forEach(function (point) {
524
- const transformed = tr.point(point);
525
- if (minX === undefined) {
526
- minX = maxX = transformed.x;
527
- minY = maxY = transformed.y;
528
- }
529
- minX = Math.min(minX, transformed.x);
530
- minY = Math.min(minY, transformed.y);
531
- maxX = Math.max(maxX, transformed.x);
532
- maxY = Math.max(maxY, transformed.y);
533
- });
534
-
535
- tr.invert();
536
- const p = tr.point({ x: minX, y: minY });
537
- return {
538
- x: p.x,
539
- y: p.y,
540
- width: maxX - minX,
541
- height: maxY - minY,
542
- rotation: Konva.getAngle(this.rotation()),
543
- };
544
- // const shapes = this.nodes().map(node => {
545
- // return this.__getNodeShape(node);
546
- // });
547
-
548
- // const box = getShapesRect(shapes);
549
- // return rotateAroundPoint(box, Konva.getAngle(this.rotation()), {
550
- // x: 0,
551
- // y: 0
552
- // });
553
- }
554
- getX() {
555
- return this._getNodeRect().x;
556
- }
557
- getY() {
558
- return this._getNodeRect().y;
559
- }
560
- getWidth() {
561
- return this._getNodeRect().width;
562
- }
563
- getHeight() {
564
- return this._getNodeRect().height;
565
- }
566
- _createElements() {
567
- this._createBack();
568
-
569
- ANCHORS_NAMES.forEach((name) => {
570
- this._createAnchor(name);
571
- });
572
-
573
- this._createAnchor('rotater');
574
- }
575
- _createAnchor(name) {
576
- const anchor = new Rect({
577
- stroke: 'rgb(0, 161, 255)',
578
- fill: 'white',
579
- strokeWidth: 1,
580
- name: name + ' _anchor',
581
- dragDistance: 0,
582
- // make it draggable,
583
- // so activating the anchor will not start drag&drop of any parent
584
- draggable: true,
585
- hitStrokeWidth: TOUCH_DEVICE ? 10 : 'auto',
586
- });
587
- const self = this;
588
- anchor.on('mousedown touchstart', function (e) {
589
- self._handleMouseDown(e);
590
- });
591
- anchor.on('dragstart', (e) => {
592
- anchor.stopDrag();
593
- e.cancelBubble = true;
594
- });
595
- anchor.on('dragend', (e) => {
596
- e.cancelBubble = true;
597
- });
598
-
599
- // add hover styling
600
- anchor.on('mouseenter', () => {
601
- const rad = Konva.getAngle(this.rotation());
602
- const rotateCursor = this.rotateAnchorCursor();
603
- const cursor = getCursor(name, rad, rotateCursor);
604
- anchor.getStage()!.content &&
605
- (anchor.getStage()!.content.style.cursor = cursor);
606
- this._cursorChange = true;
607
- });
608
- anchor.on('mouseout', () => {
609
- anchor.getStage()!.content &&
610
- (anchor.getStage()!.content.style.cursor = '');
611
- this._cursorChange = false;
612
- });
613
- this.add(anchor);
614
- }
615
- _createBack() {
616
- const back = new Shape({
617
- name: 'back',
618
- width: 0,
619
- height: 0,
620
- sceneFunc(ctx, shape) {
621
- const tr = shape.getParent() as Transformer;
622
- const padding = tr.padding();
623
- ctx.beginPath();
624
- ctx.rect(
625
- -padding,
626
- -padding,
627
- shape.width() + padding * 2,
628
- shape.height() + padding * 2
629
- );
630
- ctx.moveTo(shape.width() / 2, -padding);
631
- if (tr.rotateEnabled() && tr.rotateLineVisible()) {
632
- ctx.lineTo(
633
- shape.width() / 2,
634
- -tr.rotateAnchorOffset() * Util._sign(shape.height()) - padding
635
- );
636
- }
637
-
638
- ctx.fillStrokeShape(shape);
639
- },
640
- hitFunc: (ctx, shape) => {
641
- if (!this.shouldOverdrawWholeArea()) {
642
- return;
643
- }
644
- const padding = this.padding();
645
- ctx.beginPath();
646
- ctx.rect(
647
- -padding,
648
- -padding,
649
- shape.width() + padding * 2,
650
- shape.height() + padding * 2
651
- );
652
- ctx.fillStrokeShape(shape);
653
- },
654
- });
655
- this.add(back);
656
- this._proxyDrag(back);
657
- // do not bubble drag from the back shape
658
- // because we already "drag" whole transformer
659
- // so we don't want to trigger drag twice on transformer
660
- back.on('dragstart', (e) => {
661
- e.cancelBubble = true;
662
- });
663
- back.on('dragmove', (e) => {
664
- e.cancelBubble = true;
665
- });
666
- back.on('dragend', (e) => {
667
- e.cancelBubble = true;
668
- });
669
- // force self update when we drag with shouldOverDrawWholeArea setting
670
- this.on('dragmove', (e) => {
671
- this.update();
672
- });
673
- }
674
- _handleMouseDown(e) {
675
- // do nothing if we already transforming
676
- // that is possible to trigger with multitouch
677
- if (this._transforming) {
678
- return;
679
- }
680
- this._movingAnchorName = e.target.name().split(' ')[0];
681
-
682
- const attrs = this._getNodeRect();
683
- const width = attrs.width;
684
- const height = attrs.height;
685
-
686
- const hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
687
- this.sin = Math.abs(height / hypotenuse);
688
- this.cos = Math.abs(width / hypotenuse);
689
-
690
- if (typeof window !== 'undefined') {
691
- window.addEventListener('mousemove', this._handleMouseMove);
692
- window.addEventListener('touchmove', this._handleMouseMove);
693
- window.addEventListener('mouseup', this._handleMouseUp, true);
694
- window.addEventListener('touchend', this._handleMouseUp, true);
695
- }
696
-
697
- this._transforming = true;
698
- const ap = e.target.getAbsolutePosition();
699
- const pos = e.target.getStage().getPointerPosition();
700
- this._anchorDragOffset = {
701
- x: pos.x - ap.x,
702
- y: pos.y - ap.y,
703
- };
704
- activeTransformersCount++;
705
- this._fire('transformstart', { evt: e.evt, target: this.getNode() });
706
- this._nodes.forEach((target) => {
707
- target._fire('transformstart', { evt: e.evt, target });
708
- });
709
- }
710
- _handleMouseMove(e) {
711
- let x, y, newHypotenuse;
712
- const anchorNode = this.findOne('.' + this._movingAnchorName)!;
713
- const stage = anchorNode.getStage()!;
714
-
715
- stage.setPointersPositions(e);
716
-
717
- const pp = stage.getPointerPosition()!;
718
- let newNodePos = {
719
- x: pp.x - this._anchorDragOffset.x,
720
- y: pp.y - this._anchorDragOffset.y,
721
- };
722
- const oldAbs = anchorNode.getAbsolutePosition();
723
-
724
- if (this.anchorDragBoundFunc()) {
725
- newNodePos = this.anchorDragBoundFunc()(oldAbs, newNodePos, e);
726
- }
727
- anchorNode.setAbsolutePosition(newNodePos);
728
- const newAbs = anchorNode.getAbsolutePosition();
729
-
730
- // console.log(oldAbs, newNodePos, newAbs);
731
-
732
- if (oldAbs.x === newAbs.x && oldAbs.y === newAbs.y) {
733
- return;
734
- }
735
-
736
- // rotater is working very differently, so do it first
737
- if (this._movingAnchorName === 'rotater') {
738
- const attrs = this._getNodeRect();
739
- x = anchorNode.x() - attrs.width / 2;
740
- y = -anchorNode.y() + attrs.height / 2;
741
-
742
- // hor angle is changed?
743
- let delta = Math.atan2(-y, x) + Math.PI / 2;
744
-
745
- if (attrs.height < 0) {
746
- delta -= Math.PI;
747
- }
748
-
749
- const oldRotation = Konva.getAngle(this.rotation());
750
- const newRotation = oldRotation + delta;
751
-
752
- const tol = Konva.getAngle(this.rotationSnapTolerance());
753
- const snappedRot = getSnap(this.rotationSnaps(), newRotation, tol);
754
-
755
- const diff = snappedRot - attrs.rotation;
756
-
757
- const shape = rotateAroundCenter(attrs, diff);
758
- this._fitNodesInto(shape, e);
759
- return;
760
- }
761
-
762
- const shiftBehavior = this.shiftBehavior();
763
-
764
- let keepProportion: boolean;
765
- if (shiftBehavior === 'inverted') {
766
- keepProportion = this.keepRatio() && !e.shiftKey;
767
- } else if (shiftBehavior === 'none') {
768
- keepProportion = this.keepRatio();
769
- } else {
770
- keepProportion = this.keepRatio() || e.shiftKey;
771
- }
772
-
773
- let centeredScaling = this.centeredScaling() || e.altKey;
774
-
775
- if (this._movingAnchorName === 'top-left') {
776
- if (keepProportion) {
777
- const comparePoint = centeredScaling
778
- ? {
779
- x: this.width() / 2,
780
- y: this.height() / 2,
781
- }
782
- : {
783
- x: this.findOne('.bottom-right')!.x(),
784
- y: this.findOne('.bottom-right')!.y(),
785
- };
786
- newHypotenuse = Math.sqrt(
787
- Math.pow(comparePoint.x - anchorNode.x(), 2) +
788
- Math.pow(comparePoint.y - anchorNode.y(), 2)
789
- );
790
-
791
- const reverseX =
792
- this.findOne('.top-left')!.x() > comparePoint.x ? -1 : 1;
793
-
794
- const reverseY =
795
- this.findOne('.top-left')!.y() > comparePoint.y ? -1 : 1;
796
-
797
- x = newHypotenuse * this.cos * reverseX;
798
- y = newHypotenuse * this.sin * reverseY;
799
-
800
- this.findOne('.top-left')!.x(comparePoint.x - x);
801
- this.findOne('.top-left')!.y(comparePoint.y - y);
802
- }
803
- } else if (this._movingAnchorName === 'top-center') {
804
- this.findOne('.top-left')!.y(anchorNode.y());
805
- } else if (this._movingAnchorName === 'top-right') {
806
- if (keepProportion) {
807
- const comparePoint = centeredScaling
808
- ? {
809
- x: this.width() / 2,
810
- y: this.height() / 2,
811
- }
812
- : {
813
- x: this.findOne('.bottom-left')!.x(),
814
- y: this.findOne('.bottom-left')!.y(),
815
- };
816
-
817
- newHypotenuse = Math.sqrt(
818
- Math.pow(anchorNode.x() - comparePoint.x, 2) +
819
- Math.pow(comparePoint.y - anchorNode.y(), 2)
820
- );
821
-
822
- const reverseX =
823
- this.findOne('.top-right')!.x() < comparePoint.x ? -1 : 1;
824
-
825
- const reverseY =
826
- this.findOne('.top-right')!.y() > comparePoint.y ? -1 : 1;
827
-
828
- x = newHypotenuse * this.cos * reverseX;
829
- y = newHypotenuse * this.sin * reverseY;
830
-
831
- this.findOne('.top-right')!.x(comparePoint.x + x);
832
- this.findOne('.top-right')!.y(comparePoint.y - y);
833
- }
834
- var pos = anchorNode.position();
835
- this.findOne('.top-left')!.y(pos.y);
836
- this.findOne('.bottom-right')!.x(pos.x);
837
- } else if (this._movingAnchorName === 'middle-left') {
838
- this.findOne('.top-left')!.x(anchorNode.x());
839
- } else if (this._movingAnchorName === 'middle-right') {
840
- this.findOne('.bottom-right')!.x(anchorNode.x());
841
- } else if (this._movingAnchorName === 'bottom-left') {
842
- if (keepProportion) {
843
- const comparePoint = centeredScaling
844
- ? {
845
- x: this.width() / 2,
846
- y: this.height() / 2,
847
- }
848
- : {
849
- x: this.findOne('.top-right')!.x(),
850
- y: this.findOne('.top-right')!.y(),
851
- };
852
-
853
- newHypotenuse = Math.sqrt(
854
- Math.pow(comparePoint.x - anchorNode.x(), 2) +
855
- Math.pow(anchorNode.y() - comparePoint.y, 2)
856
- );
857
-
858
- const reverseX = comparePoint.x < anchorNode.x() ? -1 : 1;
859
-
860
- const reverseY = anchorNode.y() < comparePoint.y ? -1 : 1;
861
-
862
- x = newHypotenuse * this.cos * reverseX;
863
- y = newHypotenuse * this.sin * reverseY;
864
-
865
- anchorNode.x(comparePoint.x - x);
866
- anchorNode.y(comparePoint.y + y);
867
- }
868
-
869
- pos = anchorNode.position();
870
-
871
- this.findOne('.top-left')!.x(pos.x);
872
- this.findOne('.bottom-right')!.y(pos.y);
873
- } else if (this._movingAnchorName === 'bottom-center') {
874
- this.findOne('.bottom-right')!.y(anchorNode.y());
875
- } else if (this._movingAnchorName === 'bottom-right') {
876
- if (keepProportion) {
877
- const comparePoint = centeredScaling
878
- ? {
879
- x: this.width() / 2,
880
- y: this.height() / 2,
881
- }
882
- : {
883
- x: this.findOne('.top-left')!.x(),
884
- y: this.findOne('.top-left')!.y(),
885
- };
886
-
887
- newHypotenuse = Math.sqrt(
888
- Math.pow(anchorNode.x() - comparePoint.x, 2) +
889
- Math.pow(anchorNode.y() - comparePoint.y, 2)
890
- );
891
-
892
- const reverseX =
893
- this.findOne('.bottom-right')!.x() < comparePoint.x ? -1 : 1;
894
-
895
- const reverseY =
896
- this.findOne('.bottom-right')!.y() < comparePoint.y ? -1 : 1;
897
-
898
- x = newHypotenuse * this.cos * reverseX;
899
- y = newHypotenuse * this.sin * reverseY;
900
-
901
- this.findOne('.bottom-right')!.x(comparePoint.x + x);
902
- this.findOne('.bottom-right')!.y(comparePoint.y + y);
903
- }
904
- } else {
905
- console.error(
906
- new Error(
907
- 'Wrong position argument of selection resizer: ' +
908
- this._movingAnchorName
909
- )
910
- );
911
- }
912
-
913
- centeredScaling = this.centeredScaling() || e.altKey;
914
- if (centeredScaling) {
915
- const topLeft = this.findOne('.top-left')!;
916
- const bottomRight = this.findOne('.bottom-right')!;
917
- const topOffsetX = topLeft.x();
918
- const topOffsetY = topLeft.y();
919
-
920
- const bottomOffsetX = this.getWidth() - bottomRight.x();
921
- const bottomOffsetY = this.getHeight() - bottomRight.y();
922
-
923
- bottomRight.move({
924
- x: -topOffsetX,
925
- y: -topOffsetY,
926
- });
927
-
928
- topLeft.move({
929
- x: bottomOffsetX,
930
- y: bottomOffsetY,
931
- });
932
- }
933
-
934
- const absPos = this.findOne('.top-left')!.getAbsolutePosition();
935
-
936
- x = absPos.x;
937
- y = absPos.y;
938
-
939
- const width =
940
- this.findOne('.bottom-right')!.x() - this.findOne('.top-left')!.x();
941
-
942
- const height =
943
- this.findOne('.bottom-right')!.y() - this.findOne('.top-left')!.y();
944
-
945
- this._fitNodesInto(
946
- {
947
- x: x,
948
- y: y,
949
- width: width,
950
- height: height,
951
- rotation: Konva.getAngle(this.rotation()),
952
- },
953
- e
954
- );
955
- }
956
- _handleMouseUp(e) {
957
- this._removeEvents(e);
958
- }
959
- getAbsoluteTransform() {
960
- return this.getTransform();
961
- }
962
- _removeEvents(e?) {
963
- if (this._transforming) {
964
- this._transforming = false;
965
- if (typeof window !== 'undefined') {
966
- window.removeEventListener('mousemove', this._handleMouseMove);
967
- window.removeEventListener('touchmove', this._handleMouseMove);
968
- window.removeEventListener('mouseup', this._handleMouseUp, true);
969
- window.removeEventListener('touchend', this._handleMouseUp, true);
970
- }
971
- const node = this.getNode();
972
- activeTransformersCount--;
973
- this._fire('transformend', { evt: e, target: node });
974
- // redraw layer to restore hit graph
975
- this.getLayer()?.batchDraw();
976
-
977
- if (node) {
978
- this._nodes.forEach((target) => {
979
- target._fire('transformend', { evt: e, target });
980
- // redraw layer to restore hit graph
981
- target.getLayer()?.batchDraw();
982
- });
983
- }
984
- this._movingAnchorName = null;
985
- }
986
- }
987
- _fitNodesInto(newAttrs, evt?) {
988
- const oldAttrs = this._getNodeRect();
989
-
990
- const minSize = 1;
991
-
992
- if (Util._inRange(newAttrs.width, -this.padding() * 2 - minSize, minSize)) {
993
- this.update();
994
- return;
995
- }
996
- if (
997
- Util._inRange(newAttrs.height, -this.padding() * 2 - minSize, minSize)
998
- ) {
999
- this.update();
1000
- return;
1001
- }
1002
-
1003
- const t = new Transform();
1004
- t.rotate(Konva.getAngle(this.rotation()));
1005
- if (
1006
- this._movingAnchorName &&
1007
- newAttrs.width < 0 &&
1008
- this._movingAnchorName.indexOf('left') >= 0
1009
- ) {
1010
- const offset = t.point({
1011
- x: -this.padding() * 2,
1012
- y: 0,
1013
- });
1014
- newAttrs.x += offset.x;
1015
- newAttrs.y += offset.y;
1016
- newAttrs.width += this.padding() * 2;
1017
- this._movingAnchorName = this._movingAnchorName.replace('left', 'right');
1018
- this._anchorDragOffset.x -= offset.x;
1019
- this._anchorDragOffset.y -= offset.y;
1020
- } else if (
1021
- this._movingAnchorName &&
1022
- newAttrs.width < 0 &&
1023
- this._movingAnchorName.indexOf('right') >= 0
1024
- ) {
1025
- const offset = t.point({
1026
- x: this.padding() * 2,
1027
- y: 0,
1028
- });
1029
- this._movingAnchorName = this._movingAnchorName.replace('right', 'left');
1030
- this._anchorDragOffset.x -= offset.x;
1031
- this._anchorDragOffset.y -= offset.y;
1032
- newAttrs.width += this.padding() * 2;
1033
- }
1034
- if (
1035
- this._movingAnchorName &&
1036
- newAttrs.height < 0 &&
1037
- this._movingAnchorName.indexOf('top') >= 0
1038
- ) {
1039
- const offset = t.point({
1040
- x: 0,
1041
- y: -this.padding() * 2,
1042
- });
1043
- newAttrs.x += offset.x;
1044
- newAttrs.y += offset.y;
1045
- this._movingAnchorName = this._movingAnchorName.replace('top', 'bottom');
1046
- this._anchorDragOffset.x -= offset.x;
1047
- this._anchorDragOffset.y -= offset.y;
1048
- newAttrs.height += this.padding() * 2;
1049
- } else if (
1050
- this._movingAnchorName &&
1051
- newAttrs.height < 0 &&
1052
- this._movingAnchorName.indexOf('bottom') >= 0
1053
- ) {
1054
- const offset = t.point({
1055
- x: 0,
1056
- y: this.padding() * 2,
1057
- });
1058
- this._movingAnchorName = this._movingAnchorName.replace('bottom', 'top');
1059
- this._anchorDragOffset.x -= offset.x;
1060
- this._anchorDragOffset.y -= offset.y;
1061
- newAttrs.height += this.padding() * 2;
1062
- }
1063
-
1064
- if (this.boundBoxFunc()) {
1065
- const bounded = this.boundBoxFunc()(oldAttrs, newAttrs);
1066
- if (bounded) {
1067
- newAttrs = bounded;
1068
- } else {
1069
- Util.warn(
1070
- 'boundBoxFunc returned falsy. You should return new bound rect from it!'
1071
- );
1072
- }
1073
- }
1074
-
1075
- // base size value doesn't really matter
1076
- // we just need to think about bounding boxes as transforms
1077
- // but how?
1078
- // the idea is that we have a transformed rectangle with the size of "baseSize"
1079
- const baseSize = 10000000;
1080
- const oldTr = new Transform();
1081
- oldTr.translate(oldAttrs.x, oldAttrs.y);
1082
- oldTr.rotate(oldAttrs.rotation);
1083
- oldTr.scale(oldAttrs.width / baseSize, oldAttrs.height / baseSize);
1084
-
1085
- const newTr = new Transform();
1086
- const newScaleX = newAttrs.width / baseSize;
1087
- const newScaleY = newAttrs.height / baseSize;
1088
-
1089
- if (this.flipEnabled() === false) {
1090
- newTr.translate(newAttrs.x, newAttrs.y);
1091
- newTr.rotate(newAttrs.rotation);
1092
- newTr.translate(
1093
- newAttrs.width < 0 ? newAttrs.width : 0,
1094
- newAttrs.height < 0 ? newAttrs.height : 0
1095
- );
1096
- newTr.scale(Math.abs(newScaleX), Math.abs(newScaleY));
1097
- } else {
1098
- newTr.translate(newAttrs.x, newAttrs.y);
1099
- newTr.rotate(newAttrs.rotation);
1100
- newTr.scale(newScaleX, newScaleY);
1101
- }
1102
-
1103
- // now lets think we had [old transform] and n ow we have [new transform]
1104
- // Now, the questions is: how can we transform "parent" to go from [old transform] into [new transform]
1105
- // in equation it will be:
1106
- // [delta transform] * [old transform] = [new transform]
1107
- // that means that
1108
- // [delta transform] = [new transform] * [old transform inverted]
1109
- const delta = newTr.multiply(oldTr.invert());
1110
-
1111
- this._nodes.forEach((node) => {
1112
- // check to close this issue: https://github.com/konvajs/konva/issues/1957
1113
- // a node can be destroyed during the transformation
1114
- // probably a developer must remove it from transformer
1115
- if (!node.getStage()) {
1116
- // do we need a helping message?
1117
- // Util.error(
1118
- // 'Node is not attached to the stage. This is not allowed. Please attach the node to the stage before transforming. If node was destroyed, make sure to remove it from transformer.'
1119
- // );
1120
- return;
1121
- }
1122
- // for each node we have the same [delta transform]
1123
- // the equations is
1124
- // [delta transform] * [parent transform] * [old local transform] = [parent transform] * [new local transform]
1125
- // and we need to find [new local transform]
1126
- // [new local] = [parent inverted] * [delta] * [parent] * [old local]
1127
- const parentTransform = node.getParent()!.getAbsoluteTransform();
1128
- const localTransform = node.getTransform().copy();
1129
- // skip offset:
1130
- localTransform.translate(node.offsetX(), node.offsetY());
1131
-
1132
- const newLocalTransform = new Transform();
1133
- newLocalTransform
1134
- .multiply(parentTransform.copy().invert())
1135
- .multiply(delta)
1136
- .multiply(parentTransform)
1137
- .multiply(localTransform);
1138
-
1139
- const attrs = newLocalTransform.decompose();
1140
- node.setAttrs(attrs);
1141
- node.getLayer()?.batchDraw();
1142
- });
1143
- this.rotation(Util._getRotation(newAttrs.rotation));
1144
- // trigger transform event AFTER we update rotation
1145
- this._nodes.forEach((node) => {
1146
- this._fire('transform', { evt: evt, target: node });
1147
- node._fire('transform', { evt: evt, target: node });
1148
- });
1149
- this._resetTransformCache();
1150
- this.update();
1151
- this.getLayer()!.batchDraw();
1152
- }
1153
- /**
1154
- * force update of Konva.Transformer.
1155
- * Use it when you updated attached Konva.Group and now you need to reset transformer size
1156
- * @method
1157
- * @name Konva.Transformer#forceUpdate
1158
- */
1159
- forceUpdate() {
1160
- this._resetTransformCache();
1161
- this.update();
1162
- }
1163
-
1164
- _batchChangeChild(selector: string, attrs: any) {
1165
- const anchor = this.findOne(selector)!;
1166
- anchor.setAttrs(attrs);
1167
- }
1168
-
1169
- update() {
1170
- const attrs = this._getNodeRect();
1171
- this.rotation(Util._getRotation(attrs.rotation));
1172
- const width = attrs.width;
1173
- const height = attrs.height;
1174
-
1175
- const enabledAnchors = this.enabledAnchors();
1176
- const resizeEnabled = this.resizeEnabled();
1177
- const padding = this.padding();
1178
-
1179
- const anchorSize = this.anchorSize();
1180
- const anchors = this.find<Rect>('._anchor');
1181
- anchors.forEach((node) => {
1182
- node.setAttrs({
1183
- width: anchorSize,
1184
- height: anchorSize,
1185
- offsetX: anchorSize / 2,
1186
- offsetY: anchorSize / 2,
1187
- stroke: this.anchorStroke(),
1188
- strokeWidth: this.anchorStrokeWidth(),
1189
- fill: this.anchorFill(),
1190
- cornerRadius: this.anchorCornerRadius(),
1191
- });
1192
- });
1193
-
1194
- this._batchChangeChild('.top-left', {
1195
- x: 0,
1196
- y: 0,
1197
- offsetX: anchorSize / 2 + padding,
1198
- offsetY: anchorSize / 2 + padding,
1199
- visible: resizeEnabled && enabledAnchors.indexOf('top-left') >= 0,
1200
- });
1201
- this._batchChangeChild('.top-center', {
1202
- x: width / 2,
1203
- y: 0,
1204
- offsetY: anchorSize / 2 + padding,
1205
- visible: resizeEnabled && enabledAnchors.indexOf('top-center') >= 0,
1206
- });
1207
- this._batchChangeChild('.top-right', {
1208
- x: width,
1209
- y: 0,
1210
- offsetX: anchorSize / 2 - padding,
1211
- offsetY: anchorSize / 2 + padding,
1212
- visible: resizeEnabled && enabledAnchors.indexOf('top-right') >= 0,
1213
- });
1214
- this._batchChangeChild('.middle-left', {
1215
- x: 0,
1216
- y: height / 2,
1217
- offsetX: anchorSize / 2 + padding,
1218
- visible: resizeEnabled && enabledAnchors.indexOf('middle-left') >= 0,
1219
- });
1220
- this._batchChangeChild('.middle-right', {
1221
- x: width,
1222
- y: height / 2,
1223
- offsetX: anchorSize / 2 - padding,
1224
- visible: resizeEnabled && enabledAnchors.indexOf('middle-right') >= 0,
1225
- });
1226
- this._batchChangeChild('.bottom-left', {
1227
- x: 0,
1228
- y: height,
1229
- offsetX: anchorSize / 2 + padding,
1230
- offsetY: anchorSize / 2 - padding,
1231
- visible: resizeEnabled && enabledAnchors.indexOf('bottom-left') >= 0,
1232
- });
1233
- this._batchChangeChild('.bottom-center', {
1234
- x: width / 2,
1235
- y: height,
1236
- offsetY: anchorSize / 2 - padding,
1237
- visible: resizeEnabled && enabledAnchors.indexOf('bottom-center') >= 0,
1238
- });
1239
- this._batchChangeChild('.bottom-right', {
1240
- x: width,
1241
- y: height,
1242
- offsetX: anchorSize / 2 - padding,
1243
- offsetY: anchorSize / 2 - padding,
1244
- visible: resizeEnabled && enabledAnchors.indexOf('bottom-right') >= 0,
1245
- });
1246
-
1247
- this._batchChangeChild('.rotater', {
1248
- x: width / 2,
1249
- y: -this.rotateAnchorOffset() * Util._sign(height) - padding,
1250
- visible: this.rotateEnabled(),
1251
- });
1252
-
1253
- this._batchChangeChild('.back', {
1254
- width: width,
1255
- height: height,
1256
- visible: this.borderEnabled(),
1257
- stroke: this.borderStroke(),
1258
- strokeWidth: this.borderStrokeWidth(),
1259
- dash: this.borderDash(),
1260
- draggable: this.nodes().some((node) => node.draggable()),
1261
- x: 0,
1262
- y: 0,
1263
- });
1264
-
1265
- const styleFunc = this.anchorStyleFunc();
1266
- if (styleFunc) {
1267
- anchors.forEach((node) => {
1268
- styleFunc(node);
1269
- });
1270
- }
1271
- this.getLayer()?.batchDraw();
1272
- }
1273
- /**
1274
- * determine if transformer is in active transform
1275
- * @method
1276
- * @name Konva.Transformer#isTransforming
1277
- * @returns {Boolean}
1278
- */
1279
- isTransforming() {
1280
- return this._transforming;
1281
- }
1282
- /**
1283
- * Stop active transform action
1284
- * @method
1285
- * @name Konva.Transformer#stopTransform
1286
- * @returns {Boolean}
1287
- */
1288
- stopTransform() {
1289
- if (this._transforming) {
1290
- this._removeEvents();
1291
- const anchorNode = this.findOne('.' + this._movingAnchorName);
1292
- if (anchorNode) {
1293
- anchorNode.stopDrag();
1294
- }
1295
- }
1296
- }
1297
- destroy() {
1298
- if (this.getStage() && this._cursorChange) {
1299
- this.getStage()!.content && (this.getStage()!.content.style.cursor = '');
1300
- }
1301
- Group.prototype.destroy.call(this);
1302
- this.detach();
1303
- this._removeEvents();
1304
- return this;
1305
- }
1306
- // do not work as a container
1307
- // we will recreate inner nodes manually
1308
- toObject() {
1309
- return Node.prototype.toObject.call(this);
1310
- }
1311
-
1312
- // overwrite clone to NOT use method from Container
1313
- clone(obj?: any) {
1314
- const node = Node.prototype.clone.call(this, obj);
1315
- return node as this;
1316
- }
1317
- getClientRect() {
1318
- if (this.nodes().length > 0) {
1319
- return super.getClientRect();
1320
- } else {
1321
- // if we are detached return zero size
1322
- // so it will be skipped in calculations
1323
- return { x: 0, y: 0, width: 0, height: 0 };
1324
- }
1325
- }
1326
-
1327
- nodes: GetSet<Node[], this>;
1328
- enabledAnchors: GetSet<string[], this>;
1329
- rotationSnaps: GetSet<number[], this>;
1330
- anchorSize: GetSet<number, this>;
1331
- resizeEnabled: GetSet<boolean, this>;
1332
- rotateEnabled: GetSet<boolean, this>;
1333
- rotateLineVisible: GetSet<boolean, this>;
1334
- rotateAnchorOffset: GetSet<number, this>;
1335
- rotationSnapTolerance: GetSet<number, this>;
1336
- rotateAnchorCursor: GetSet<string, this>;
1337
- padding: GetSet<number, this>;
1338
- borderEnabled: GetSet<boolean, this>;
1339
- borderStroke: GetSet<string, this>;
1340
- borderStrokeWidth: GetSet<number, this>;
1341
- borderDash: GetSet<number[], this>;
1342
- anchorFill: GetSet<string, this>;
1343
- anchorStroke: GetSet<string, this>;
1344
- anchorCornerRadius: GetSet<number, this>;
1345
- anchorStrokeWidth: GetSet<number, this>;
1346
- keepRatio: GetSet<boolean, this>;
1347
- shiftBehavior: GetSet<string, this>;
1348
- centeredScaling: GetSet<boolean, this>;
1349
- flipEnabled: GetSet<boolean, this>;
1350
- ignoreStroke: GetSet<boolean, this>;
1351
- boundBoxFunc: GetSet<(oldBox: Box, newBox: Box) => Box, this>;
1352
- anchorDragBoundFunc: GetSet<
1353
- (oldPos: Vector2d, newPos: Vector2d, e: MouseEvent) => Vector2d,
1354
- this
1355
- >;
1356
- anchorStyleFunc: GetSet<null | ((Node: Rect) => void), this>;
1357
- shouldOverdrawWholeArea: GetSet<boolean, this>;
1358
- useSingleNodeRotation: GetSet<boolean, this>;
1359
- }
1360
-
1361
- function validateAnchors(val) {
1362
- if (!(val instanceof Array)) {
1363
- Util.warn('enabledAnchors value should be an array');
1364
- }
1365
- if (val instanceof Array) {
1366
- val.forEach(function (name) {
1367
- if (ANCHORS_NAMES.indexOf(name) === -1) {
1368
- Util.warn(
1369
- 'Unknown anchor name: ' +
1370
- name +
1371
- '. Available names are: ' +
1372
- ANCHORS_NAMES.join(', ')
1373
- );
1374
- }
1375
- });
1376
- }
1377
- return val || [];
1378
- }
1379
-
1380
- Transformer.prototype.className = 'Transformer';
1381
- _registerNode(Transformer);
1382
-
1383
- /**
1384
- * get/set enabled handlers
1385
- * @name Konva.Transformer#enabledAnchors
1386
- * @method
1387
- * @param {Array} array
1388
- * @returns {Array}
1389
- * @example
1390
- * // get list of handlers
1391
- * var enabledAnchors = transformer.enabledAnchors();
1392
- *
1393
- * // set handlers
1394
- * transformer.enabledAnchors(['top-left', 'top-center', 'top-right', 'middle-right', 'middle-left', 'bottom-left', 'bottom-center', 'bottom-right']);
1395
- */
1396
- Factory.addGetterSetter(
1397
- Transformer,
1398
- 'enabledAnchors',
1399
- ANCHORS_NAMES,
1400
- validateAnchors
1401
- );
1402
-
1403
- /**
1404
- * get/set flip enabled
1405
- * @name Konva.Transformer#flipEnabled
1406
- * @method
1407
- * @param {Boolean} flag
1408
- * @returns {Boolean}
1409
- * @example
1410
- * // get flip enabled property
1411
- * var flipEnabled = transformer.flipEnabled();
1412
- *
1413
- * // set flip enabled property
1414
- * transformer.flipEnabled(false);
1415
- */
1416
- Factory.addGetterSetter(
1417
- Transformer,
1418
- 'flipEnabled',
1419
- true,
1420
- getBooleanValidator()
1421
- );
1422
-
1423
- /**
1424
- * get/set resize ability. If false it will automatically hide resizing handlers
1425
- * @name Konva.Transformer#resizeEnabled
1426
- * @method
1427
- * @param {Boolean} enabled
1428
- * @returns {Boolean}
1429
- * @example
1430
- * // get
1431
- * var resizeEnabled = transformer.resizeEnabled();
1432
- *
1433
- * // set
1434
- * transformer.resizeEnabled(false);
1435
- */
1436
- Factory.addGetterSetter(Transformer, 'resizeEnabled', true);
1437
- /**
1438
- * get/set anchor size. Default is 10
1439
- * @name Konva.Transformer#anchorSize
1440
- * @method
1441
- * @param {Number} size
1442
- * @returns {Number}
1443
- * @example
1444
- * // get
1445
- * var anchorSize = transformer.anchorSize();
1446
- *
1447
- * // set
1448
- * transformer.anchorSize(20)
1449
- */
1450
- Factory.addGetterSetter(Transformer, 'anchorSize', 10, getNumberValidator());
1451
-
1452
- /**
1453
- * get/set ability to rotate.
1454
- * @name Konva.Transformer#rotateEnabled
1455
- * @method
1456
- * @param {Boolean} enabled
1457
- * @returns {Boolean}
1458
- * @example
1459
- * // get
1460
- * var rotateEnabled = transformer.rotateEnabled();
1461
- *
1462
- * // set
1463
- * transformer.rotateEnabled(false);
1464
- */
1465
- Factory.addGetterSetter(Transformer, 'rotateEnabled', true);
1466
-
1467
- /**
1468
- * get/set visibility of a little line that connects transformer and rotate anchor.
1469
- * @name Konva.Transformer#rotateLineVisible
1470
- * @method
1471
- * @param {Boolean} enabled
1472
- * @returns {Boolean}
1473
- * @example
1474
- * // get
1475
- * var rotateLineVisible = transformer.rotateLineVisible();
1476
- *
1477
- * // set
1478
- * transformer.rotateLineVisible(false);
1479
- */
1480
- Factory.addGetterSetter(Transformer, 'rotateLineVisible', true);
1481
-
1482
- /**
1483
- * get/set rotation snaps angles.
1484
- * @name Konva.Transformer#rotationSnaps
1485
- * @method
1486
- * @param {Array} array
1487
- * @returns {Array}
1488
- * @example
1489
- * // get
1490
- * var rotationSnaps = transformer.rotationSnaps();
1491
- *
1492
- * // set
1493
- * transformer.rotationSnaps([0, 90, 180, 270]);
1494
- */
1495
- Factory.addGetterSetter(Transformer, 'rotationSnaps', []);
1496
-
1497
- /**
1498
- * get/set distance for rotation handler
1499
- * @name Konva.Transformer#rotateAnchorOffset
1500
- * @method
1501
- * @param {Number} offset
1502
- * @returns {Number}
1503
- * @example
1504
- * // get
1505
- * var rotateAnchorOffset = transformer.rotateAnchorOffset();
1506
- *
1507
- * // set
1508
- * transformer.rotateAnchorOffset(100);
1509
- */
1510
- Factory.addGetterSetter(
1511
- Transformer,
1512
- 'rotateAnchorOffset',
1513
- 50,
1514
- getNumberValidator()
1515
- );
1516
-
1517
- /**
1518
- * get/set rotation anchor cursor
1519
- * @name Konva.Transformer#rotateAnchorCursor
1520
- * @method
1521
- * @param {String} cursorName
1522
- * @returns {String}
1523
- * @example
1524
- * // get
1525
- * var currentRotationAnchorCursor = transformer.rotateAnchorCursor();
1526
- *
1527
- * // set
1528
- * transformer.rotateAnchorCursor('grab');
1529
- */
1530
- Factory.addGetterSetter(Transformer, 'rotateAnchorCursor', 'crosshair');
1531
-
1532
- /**
1533
- * get/set distance for rotation tolerance
1534
- * @name Konva.Transformer#rotationSnapTolerance
1535
- * @method
1536
- * @param {Number} tolerance
1537
- * @returns {Number}
1538
- * @example
1539
- * // get
1540
- * var rotationSnapTolerance = transformer.rotationSnapTolerance();
1541
- *
1542
- * // set
1543
- * transformer.rotationSnapTolerance(100);
1544
- */
1545
- Factory.addGetterSetter(
1546
- Transformer,
1547
- 'rotationSnapTolerance',
1548
- 5,
1549
- getNumberValidator()
1550
- );
1551
-
1552
- /**
1553
- * get/set visibility of border
1554
- * @name Konva.Transformer#borderEnabled
1555
- * @method
1556
- * @param {Boolean} enabled
1557
- * @returns {Boolean}
1558
- * @example
1559
- * // get
1560
- * var borderEnabled = transformer.borderEnabled();
1561
- *
1562
- * // set
1563
- * transformer.borderEnabled(false);
1564
- */
1565
- Factory.addGetterSetter(Transformer, 'borderEnabled', true);
1566
-
1567
- /**
1568
- * get/set anchor stroke color
1569
- * @name Konva.Transformer#anchorStroke
1570
- * @method
1571
- * @param {String} strokeColor
1572
- * @returns {String}
1573
- * @example
1574
- * // get
1575
- * var anchorStroke = transformer.anchorStroke();
1576
- *
1577
- * // set
1578
- * transformer.anchorStroke('red');
1579
- */
1580
- Factory.addGetterSetter(Transformer, 'anchorStroke', 'rgb(0, 161, 255)');
1581
-
1582
- /**
1583
- * get/set anchor stroke width
1584
- * @name Konva.Transformer#anchorStrokeWidth
1585
- * @method
1586
- * @param {Number} anchorStrokeWidth
1587
- * @returns {Number}
1588
- * @example
1589
- * // get
1590
- * var anchorStrokeWidth = transformer.anchorStrokeWidth();
1591
- *
1592
- * // set
1593
- * transformer.anchorStrokeWidth(3);
1594
- */
1595
- Factory.addGetterSetter(
1596
- Transformer,
1597
- 'anchorStrokeWidth',
1598
- 1,
1599
- getNumberValidator()
1600
- );
1601
-
1602
- /**
1603
- * get/set anchor fill color
1604
- * @name Konva.Transformer#anchorFill
1605
- * @method
1606
- * @param {String} anchorFill
1607
- * @returns {String}
1608
- * @example
1609
- * // get
1610
- * var anchorFill = transformer.anchorFill();
1611
- *
1612
- * // set
1613
- * transformer.anchorFill('red');
1614
- */
1615
- Factory.addGetterSetter(Transformer, 'anchorFill', 'white');
1616
-
1617
- /**
1618
- * get/set anchor corner radius
1619
- * @name Konva.Transformer#anchorCornerRadius
1620
- * @method
1621
- * @param {Number} radius
1622
- * @returns {Number}
1623
- * @example
1624
- * // get
1625
- * var anchorCornerRadius = transformer.anchorCornerRadius();
1626
- *
1627
- * // set
1628
- * transformer.anchorCornerRadius(3);
1629
- */
1630
- Factory.addGetterSetter(
1631
- Transformer,
1632
- 'anchorCornerRadius',
1633
- 0,
1634
- getNumberValidator()
1635
- );
1636
-
1637
- /**
1638
- * get/set border stroke color
1639
- * @name Konva.Transformer#borderStroke
1640
- * @method
1641
- * @param {Boolean} enabled
1642
- * @returns {Boolean}
1643
- * @example
1644
- * // get
1645
- * var borderStroke = transformer.borderStroke();
1646
- *
1647
- * // set
1648
- * transformer.borderStroke('red');
1649
- */
1650
- Factory.addGetterSetter(Transformer, 'borderStroke', 'rgb(0, 161, 255)');
1651
-
1652
- /**
1653
- * get/set border stroke width
1654
- * @name Konva.Transformer#borderStrokeWidth
1655
- * @method
1656
- * @param {Number} strokeWidth
1657
- * @returns {Number}
1658
- * @example
1659
- * // get
1660
- * var borderStrokeWidth = transformer.borderStrokeWidth();
1661
- *
1662
- * // set
1663
- * transformer.borderStrokeWidth(3);
1664
- */
1665
- Factory.addGetterSetter(
1666
- Transformer,
1667
- 'borderStrokeWidth',
1668
- 1,
1669
- getNumberValidator()
1670
- );
1671
-
1672
- /**
1673
- * get/set border dash array
1674
- * @name Konva.Transformer#borderDash
1675
- * @method
1676
- * @param {Array} dash array
1677
- * @returns {Array}
1678
- * @example
1679
- * // get
1680
- * var borderDash = transformer.borderDash();
1681
- *
1682
- * // set
1683
- * transformer.borderDash([2, 2]);
1684
- */
1685
- Factory.addGetterSetter(Transformer, 'borderDash');
1686
-
1687
- /**
1688
- * get/set should we keep ratio while resize anchors at corners
1689
- * @name Konva.Transformer#keepRatio
1690
- * @method
1691
- * @param {Boolean} keepRatio
1692
- * @returns {Boolean}
1693
- * @example
1694
- * // get
1695
- * var keepRatio = transformer.keepRatio();
1696
- *
1697
- * // set
1698
- * transformer.keepRatio(false);
1699
- */
1700
- Factory.addGetterSetter(Transformer, 'keepRatio', true);
1701
-
1702
- /**
1703
- * get/set how to react on skift key while resizing anchors at corners
1704
- * @name Konva.Transformer#shiftBehavior
1705
- * @method
1706
- * @param {String} shiftBehavior
1707
- * @returns {String}
1708
- * @example
1709
- * // get
1710
- * var shiftBehavior = transformer.shiftBehavior();
1711
- *
1712
- * // set
1713
- * transformer.shiftBehavior('none');
1714
- */
1715
- Factory.addGetterSetter(Transformer, 'shiftBehavior', 'default');
1716
-
1717
- /**
1718
- * get/set should we resize relative to node's center?
1719
- * @name Konva.Transformer#centeredScaling
1720
- * @method
1721
- * @param {Boolean} centeredScaling
1722
- * @returns {Boolean}
1723
- * @example
1724
- * // get
1725
- * var centeredScaling = transformer.centeredScaling();
1726
- *
1727
- * // set
1728
- * transformer.centeredScaling(true);
1729
- */
1730
- Factory.addGetterSetter(Transformer, 'centeredScaling', false);
1731
-
1732
- /**
1733
- * get/set should we think about stroke while resize? Good to use when a shape has strokeScaleEnabled = false
1734
- * default is false
1735
- * @name Konva.Transformer#ignoreStroke
1736
- * @method
1737
- * @param {Boolean} ignoreStroke
1738
- * @returns {Boolean}
1739
- * @example
1740
- * // get
1741
- * var ignoreStroke = transformer.ignoreStroke();
1742
- *
1743
- * // set
1744
- * transformer.ignoreStroke(true);
1745
- */
1746
- Factory.addGetterSetter(Transformer, 'ignoreStroke', false);
1747
-
1748
- /**
1749
- * get/set padding
1750
- * @name Konva.Transformer#padding
1751
- * @method
1752
- * @param {Number} padding
1753
- * @returns {Number}
1754
- * @example
1755
- * // get
1756
- * var padding = transformer.padding();
1757
- *
1758
- * // set
1759
- * transformer.padding(10);
1760
- */
1761
- Factory.addGetterSetter(Transformer, 'padding', 0, getNumberValidator());
1762
-
1763
- /**
1764
- * get/set attached nodes of the Transformer. Transformer will adapt to their size and listen to their events
1765
- * @method
1766
- * @name Konva.Transformer#nodes
1767
- * @returns {Konva.Node}
1768
- * @example
1769
- * // get
1770
- * const nodes = transformer.nodes();
1771
- *
1772
- * // set
1773
- * transformer.nodes([rect, circle]);
1774
- *
1775
- * // push new item:
1776
- * const oldNodes = transformer.nodes();
1777
- * const newNodes = oldNodes.concat([newShape]);
1778
- * // it is important to set new array instance (and concat method above will create it)
1779
- * transformer.nodes(newNodes);
1780
- */
1781
-
1782
- Factory.addGetterSetter(Transformer, 'nodes');
1783
- // @ts-ignore
1784
- // deprecated
1785
- Factory.addGetterSetter(Transformer, 'node');
1786
-
1787
- /**
1788
- * get/set bounding box function. **IMPORTANT!** boundBondFunc operates in absolute coordinates.
1789
- * @name Konva.Transformer#boundBoxFunc
1790
- * @method
1791
- * @param {Function} func
1792
- * @returns {Function}
1793
- * @example
1794
- * // get
1795
- * var boundBoxFunc = transformer.boundBoxFunc();
1796
- *
1797
- * // set
1798
- * transformer.boundBoxFunc(function(oldBox, newBox) {
1799
- * // width and height of the boxes are corresponding to total absolute width and height of all nodes combined
1800
- * // so it includes scale of the node.
1801
- * if (newBox.width > 200) {
1802
- * return oldBox;
1803
- * }
1804
- * return newBox;
1805
- * });
1806
- */
1807
- Factory.addGetterSetter(Transformer, 'boundBoxFunc');
1808
-
1809
- /**
1810
- * get/set dragging func for transformer anchors
1811
- * @name Konva.Transformer#anchorDragBoundFunc
1812
- * @method
1813
- * @param {Function} func
1814
- * @returns {Function}
1815
- * @example
1816
- * // get
1817
- * var anchorDragBoundFunc = transformer.anchorDragBoundFunc();
1818
- *
1819
- * // set
1820
- * transformer.anchorDragBoundFunc(function(oldAbsPos, newAbsPos, event) {
1821
- * return {
1822
- * x: 0,
1823
- * y: newAbsolutePosition.y
1824
- * }
1825
- * });
1826
- */
1827
- Factory.addGetterSetter(Transformer, 'anchorDragBoundFunc');
1828
-
1829
- /**
1830
- * get/set styling function for transformer anchors to overwrite default styles
1831
- * @name Konva.Transformer#anchorStyleFunc
1832
- * @method
1833
- * @param {Function} func
1834
- * @returns {Function}
1835
- * @example
1836
- * // get
1837
- * var anchorStyleFunc = transformer.anchorStyleFunc();
1838
- *
1839
- * // set
1840
- * transformer.anchorStyleFunc(function(anchor) {
1841
- * // anchor is a simple Konva.Rect instance
1842
- * // it will be executed AFTER all attributes are set, like 'anchorStrokeWidth' or 'anchorFill'
1843
- * if (anchor.hasName('.rotater')) {
1844
- * // make rotater anchor filled black and looks like a circle
1845
- * anchor.fill('black');
1846
- * anchor.cornerRadius(anchor.width() / 2);
1847
- * }
1848
- * });
1849
- */
1850
- Factory.addGetterSetter(Transformer, 'anchorStyleFunc');
1851
-
1852
- /**
1853
- * using this setting you can drag transformer group by dragging empty space between attached nodes
1854
- * shouldOverdrawWholeArea = true may temporary disable all events on attached nodes
1855
- * @name Konva.Transformer#shouldOverdrawWholeArea
1856
- * @method
1857
- * @param {Boolean} shouldOverdrawWholeArea
1858
- * @returns {Boolean}
1859
- * @example
1860
- * // get
1861
- * var shouldOverdrawWholeArea = transformer.shouldOverdrawWholeArea();
1862
- *
1863
- * // set
1864
- * transformer.shouldOverdrawWholeArea(true);
1865
- */
1866
- Factory.addGetterSetter(Transformer, 'shouldOverdrawWholeArea', false);
1867
-
1868
- /**
1869
- * If you have just one attached node to Transformer it will set its initial rotation to the rotation of that node.
1870
- * In some cases you may need to set a different rotation.
1871
- * @name Konva.Transformer#useSingleNodeRotation
1872
- * @method
1873
- * @param {Boolean} useSingleNodeRotation
1874
- * @returns {Boolean}
1875
- * @example
1876
- * // set flag to false
1877
- * transformer.useSingleNodeRotation(false);
1878
- * // attach a shape
1879
- * transformer.nodes([shape]);
1880
- * transformer.rotation(45);
1881
- * transformer.update();
1882
- */
1883
- Factory.addGetterSetter(Transformer, 'useSingleNodeRotation', true);
1884
-
1885
- Factory.backCompat(Transformer, {
1886
- lineEnabled: 'borderEnabled',
1887
- rotateHandlerOffset: 'rotateAnchorOffset',
1888
- enabledHandlers: 'enabledAnchors',
1889
- });