source: imaps-frontend/node_modules/konva/lib/shapes/Transformer.js@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 38.1 KB
Line 
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.Transformer = void 0;
4const Util_1 = require("../Util");
5const Factory_1 = require("../Factory");
6const Node_1 = require("../Node");
7const Shape_1 = require("../Shape");
8const Rect_1 = require("./Rect");
9const Group_1 = require("../Group");
10const Global_1 = require("../Global");
11const Validators_1 = require("../Validators");
12const Global_2 = require("../Global");
13var EVENTS_NAME = 'tr-konva';
14var ATTR_CHANGE_LIST = [
15 'resizeEnabledChange',
16 'rotateAnchorOffsetChange',
17 'rotateEnabledChange',
18 'enabledAnchorsChange',
19 'anchorSizeChange',
20 'borderEnabledChange',
21 'borderStrokeChange',
22 'borderStrokeWidthChange',
23 'borderDashChange',
24 'anchorStrokeChange',
25 'anchorStrokeWidthChange',
26 'anchorFillChange',
27 'anchorCornerRadiusChange',
28 'ignoreStrokeChange',
29 'anchorStyleFuncChange',
30]
31 .map((e) => e + `.${EVENTS_NAME}`)
32 .join(' ');
33var NODES_RECT = 'nodesRect';
34var TRANSFORM_CHANGE_STR = [
35 'widthChange',
36 'heightChange',
37 'scaleXChange',
38 'scaleYChange',
39 'skewXChange',
40 'skewYChange',
41 'rotationChange',
42 'offsetXChange',
43 'offsetYChange',
44 'transformsEnabledChange',
45 'strokeWidthChange',
46];
47var ANGLES = {
48 'top-left': -45,
49 'top-center': 0,
50 'top-right': 45,
51 'middle-right': -90,
52 'middle-left': 90,
53 'bottom-left': -135,
54 'bottom-center': 180,
55 'bottom-right': 135,
56};
57const TOUCH_DEVICE = 'ontouchstart' in Global_1.Konva._global;
58function getCursor(anchorName, rad, rotateCursor) {
59 if (anchorName === 'rotater') {
60 return rotateCursor;
61 }
62 rad += Util_1.Util.degToRad(ANGLES[anchorName] || 0);
63 var angle = ((Util_1.Util.radToDeg(rad) % 360) + 360) % 360;
64 if (Util_1.Util._inRange(angle, 315 + 22.5, 360) || Util_1.Util._inRange(angle, 0, 22.5)) {
65 return 'ns-resize';
66 }
67 else if (Util_1.Util._inRange(angle, 45 - 22.5, 45 + 22.5)) {
68 return 'nesw-resize';
69 }
70 else if (Util_1.Util._inRange(angle, 90 - 22.5, 90 + 22.5)) {
71 return 'ew-resize';
72 }
73 else if (Util_1.Util._inRange(angle, 135 - 22.5, 135 + 22.5)) {
74 return 'nwse-resize';
75 }
76 else if (Util_1.Util._inRange(angle, 180 - 22.5, 180 + 22.5)) {
77 return 'ns-resize';
78 }
79 else if (Util_1.Util._inRange(angle, 225 - 22.5, 225 + 22.5)) {
80 return 'nesw-resize';
81 }
82 else if (Util_1.Util._inRange(angle, 270 - 22.5, 270 + 22.5)) {
83 return 'ew-resize';
84 }
85 else if (Util_1.Util._inRange(angle, 315 - 22.5, 315 + 22.5)) {
86 return 'nwse-resize';
87 }
88 else {
89 Util_1.Util.error('Transformer has unknown angle for cursor detection: ' + angle);
90 return 'pointer';
91 }
92}
93var ANCHORS_NAMES = [
94 'top-left',
95 'top-center',
96 'top-right',
97 'middle-right',
98 'middle-left',
99 'bottom-left',
100 'bottom-center',
101 'bottom-right',
102];
103var MAX_SAFE_INTEGER = 100000000;
104function getCenter(shape) {
105 return {
106 x: shape.x +
107 (shape.width / 2) * Math.cos(shape.rotation) +
108 (shape.height / 2) * Math.sin(-shape.rotation),
109 y: shape.y +
110 (shape.height / 2) * Math.cos(shape.rotation) +
111 (shape.width / 2) * Math.sin(shape.rotation),
112 };
113}
114function rotateAroundPoint(shape, angleRad, point) {
115 const x = point.x +
116 (shape.x - point.x) * Math.cos(angleRad) -
117 (shape.y - point.y) * Math.sin(angleRad);
118 const y = point.y +
119 (shape.x - point.x) * Math.sin(angleRad) +
120 (shape.y - point.y) * Math.cos(angleRad);
121 return {
122 ...shape,
123 rotation: shape.rotation + angleRad,
124 x,
125 y,
126 };
127}
128function rotateAroundCenter(shape, deltaRad) {
129 const center = getCenter(shape);
130 return rotateAroundPoint(shape, deltaRad, center);
131}
132function getSnap(snaps, newRotationRad, tol) {
133 let snapped = newRotationRad;
134 for (let i = 0; i < snaps.length; i++) {
135 const angle = Global_1.Konva.getAngle(snaps[i]);
136 const absDiff = Math.abs(angle - newRotationRad) % (Math.PI * 2);
137 const dif = Math.min(absDiff, Math.PI * 2 - absDiff);
138 if (dif < tol) {
139 snapped = angle;
140 }
141 }
142 return snapped;
143}
144let activeTransformersCount = 0;
145class Transformer extends Group_1.Group {
146 constructor(config) {
147 super(config);
148 this._movingAnchorName = null;
149 this._transforming = false;
150 this._createElements();
151 this._handleMouseMove = this._handleMouseMove.bind(this);
152 this._handleMouseUp = this._handleMouseUp.bind(this);
153 this.update = this.update.bind(this);
154 this.on(ATTR_CHANGE_LIST, this.update);
155 if (this.getNode()) {
156 this.update();
157 }
158 }
159 attachTo(node) {
160 this.setNode(node);
161 return this;
162 }
163 setNode(node) {
164 Util_1.Util.warn('tr.setNode(shape), tr.node(shape) and tr.attachTo(shape) methods are deprecated. Please use tr.nodes(nodesArray) instead.');
165 return this.setNodes([node]);
166 }
167 getNode() {
168 return this._nodes && this._nodes[0];
169 }
170 _getEventNamespace() {
171 return EVENTS_NAME + this._id;
172 }
173 setNodes(nodes = []) {
174 if (this._nodes && this._nodes.length) {
175 this.detach();
176 }
177 const filteredNodes = nodes.filter((node) => {
178 if (node.isAncestorOf(this)) {
179 Util_1.Util.error('Konva.Transformer cannot be an a child of the node you are trying to attach');
180 return false;
181 }
182 return true;
183 });
184 this._nodes = nodes = filteredNodes;
185 if (nodes.length === 1 && this.useSingleNodeRotation()) {
186 this.rotation(nodes[0].getAbsoluteRotation());
187 }
188 else {
189 this.rotation(0);
190 }
191 this._nodes.forEach((node) => {
192 const onChange = () => {
193 if (this.nodes().length === 1 && this.useSingleNodeRotation()) {
194 this.rotation(this.nodes()[0].getAbsoluteRotation());
195 }
196 this._resetTransformCache();
197 if (!this._transforming && !this.isDragging()) {
198 this.update();
199 }
200 };
201 const additionalEvents = node._attrsAffectingSize
202 .map((prop) => prop + 'Change.' + this._getEventNamespace())
203 .join(' ');
204 node.on(additionalEvents, onChange);
205 node.on(TRANSFORM_CHANGE_STR.map((e) => e + `.${this._getEventNamespace()}`).join(' '), onChange);
206 node.on(`absoluteTransformChange.${this._getEventNamespace()}`, onChange);
207 this._proxyDrag(node);
208 });
209 this._resetTransformCache();
210 var elementsCreated = !!this.findOne('.top-left');
211 if (elementsCreated) {
212 this.update();
213 }
214 return this;
215 }
216 _proxyDrag(node) {
217 let lastPos;
218 node.on(`dragstart.${this._getEventNamespace()}`, (e) => {
219 lastPos = node.getAbsolutePosition();
220 if (!this.isDragging() && node !== this.findOne('.back')) {
221 this.startDrag(e, false);
222 }
223 });
224 node.on(`dragmove.${this._getEventNamespace()}`, (e) => {
225 if (!lastPos) {
226 return;
227 }
228 const abs = node.getAbsolutePosition();
229 const dx = abs.x - lastPos.x;
230 const dy = abs.y - lastPos.y;
231 this.nodes().forEach((otherNode) => {
232 if (otherNode === node) {
233 return;
234 }
235 if (otherNode.isDragging()) {
236 return;
237 }
238 const otherAbs = otherNode.getAbsolutePosition();
239 otherNode.setAbsolutePosition({
240 x: otherAbs.x + dx,
241 y: otherAbs.y + dy,
242 });
243 otherNode.startDrag(e);
244 });
245 lastPos = null;
246 });
247 }
248 getNodes() {
249 return this._nodes || [];
250 }
251 getActiveAnchor() {
252 return this._movingAnchorName;
253 }
254 detach() {
255 if (this._nodes) {
256 this._nodes.forEach((node) => {
257 node.off('.' + this._getEventNamespace());
258 });
259 }
260 this._nodes = [];
261 this._resetTransformCache();
262 }
263 _resetTransformCache() {
264 this._clearCache(NODES_RECT);
265 this._clearCache('transform');
266 this._clearSelfAndDescendantCache('absoluteTransform');
267 }
268 _getNodeRect() {
269 return this._getCache(NODES_RECT, this.__getNodeRect);
270 }
271 __getNodeShape(node, rot = this.rotation(), relative) {
272 var rect = node.getClientRect({
273 skipTransform: true,
274 skipShadow: true,
275 skipStroke: this.ignoreStroke(),
276 });
277 var absScale = node.getAbsoluteScale(relative);
278 var absPos = node.getAbsolutePosition(relative);
279 var dx = rect.x * absScale.x - node.offsetX() * absScale.x;
280 var dy = rect.y * absScale.y - node.offsetY() * absScale.y;
281 const rotation = (Global_1.Konva.getAngle(node.getAbsoluteRotation()) + Math.PI * 2) %
282 (Math.PI * 2);
283 const box = {
284 x: absPos.x + dx * Math.cos(rotation) + dy * Math.sin(-rotation),
285 y: absPos.y + dy * Math.cos(rotation) + dx * Math.sin(rotation),
286 width: rect.width * absScale.x,
287 height: rect.height * absScale.y,
288 rotation: rotation,
289 };
290 return rotateAroundPoint(box, -Global_1.Konva.getAngle(rot), {
291 x: 0,
292 y: 0,
293 });
294 }
295 __getNodeRect() {
296 var node = this.getNode();
297 if (!node) {
298 return {
299 x: -MAX_SAFE_INTEGER,
300 y: -MAX_SAFE_INTEGER,
301 width: 0,
302 height: 0,
303 rotation: 0,
304 };
305 }
306 const totalPoints = [];
307 this.nodes().map((node) => {
308 const box = node.getClientRect({
309 skipTransform: true,
310 skipShadow: true,
311 skipStroke: this.ignoreStroke(),
312 });
313 var points = [
314 { x: box.x, y: box.y },
315 { x: box.x + box.width, y: box.y },
316 { x: box.x + box.width, y: box.y + box.height },
317 { x: box.x, y: box.y + box.height },
318 ];
319 var trans = node.getAbsoluteTransform();
320 points.forEach(function (point) {
321 var transformed = trans.point(point);
322 totalPoints.push(transformed);
323 });
324 });
325 const tr = new Util_1.Transform();
326 tr.rotate(-Global_1.Konva.getAngle(this.rotation()));
327 var minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
328 totalPoints.forEach(function (point) {
329 var transformed = tr.point(point);
330 if (minX === undefined) {
331 minX = maxX = transformed.x;
332 minY = maxY = transformed.y;
333 }
334 minX = Math.min(minX, transformed.x);
335 minY = Math.min(minY, transformed.y);
336 maxX = Math.max(maxX, transformed.x);
337 maxY = Math.max(maxY, transformed.y);
338 });
339 tr.invert();
340 const p = tr.point({ x: minX, y: minY });
341 return {
342 x: p.x,
343 y: p.y,
344 width: maxX - minX,
345 height: maxY - minY,
346 rotation: Global_1.Konva.getAngle(this.rotation()),
347 };
348 }
349 getX() {
350 return this._getNodeRect().x;
351 }
352 getY() {
353 return this._getNodeRect().y;
354 }
355 getWidth() {
356 return this._getNodeRect().width;
357 }
358 getHeight() {
359 return this._getNodeRect().height;
360 }
361 _createElements() {
362 this._createBack();
363 ANCHORS_NAMES.forEach((name) => {
364 this._createAnchor(name);
365 });
366 this._createAnchor('rotater');
367 }
368 _createAnchor(name) {
369 var anchor = new Rect_1.Rect({
370 stroke: 'rgb(0, 161, 255)',
371 fill: 'white',
372 strokeWidth: 1,
373 name: name + ' _anchor',
374 dragDistance: 0,
375 draggable: true,
376 hitStrokeWidth: TOUCH_DEVICE ? 10 : 'auto',
377 });
378 var self = this;
379 anchor.on('mousedown touchstart', function (e) {
380 self._handleMouseDown(e);
381 });
382 anchor.on('dragstart', (e) => {
383 anchor.stopDrag();
384 e.cancelBubble = true;
385 });
386 anchor.on('dragend', (e) => {
387 e.cancelBubble = true;
388 });
389 anchor.on('mouseenter', () => {
390 var rad = Global_1.Konva.getAngle(this.rotation());
391 var rotateCursor = this.rotateAnchorCursor();
392 var cursor = getCursor(name, rad, rotateCursor);
393 anchor.getStage().content &&
394 (anchor.getStage().content.style.cursor = cursor);
395 this._cursorChange = true;
396 });
397 anchor.on('mouseout', () => {
398 anchor.getStage().content &&
399 (anchor.getStage().content.style.cursor = '');
400 this._cursorChange = false;
401 });
402 this.add(anchor);
403 }
404 _createBack() {
405 var back = new Shape_1.Shape({
406 name: 'back',
407 width: 0,
408 height: 0,
409 draggable: true,
410 sceneFunc(ctx, shape) {
411 var tr = shape.getParent();
412 var padding = tr.padding();
413 ctx.beginPath();
414 ctx.rect(-padding, -padding, shape.width() + padding * 2, shape.height() + padding * 2);
415 ctx.moveTo(shape.width() / 2, -padding);
416 if (tr.rotateEnabled() && tr.rotateLineVisible()) {
417 ctx.lineTo(shape.width() / 2, -tr.rotateAnchorOffset() * Util_1.Util._sign(shape.height()) - padding);
418 }
419 ctx.fillStrokeShape(shape);
420 },
421 hitFunc: (ctx, shape) => {
422 if (!this.shouldOverdrawWholeArea()) {
423 return;
424 }
425 var padding = this.padding();
426 ctx.beginPath();
427 ctx.rect(-padding, -padding, shape.width() + padding * 2, shape.height() + padding * 2);
428 ctx.fillStrokeShape(shape);
429 },
430 });
431 this.add(back);
432 this._proxyDrag(back);
433 back.on('dragstart', (e) => {
434 e.cancelBubble = true;
435 });
436 back.on('dragmove', (e) => {
437 e.cancelBubble = true;
438 });
439 back.on('dragend', (e) => {
440 e.cancelBubble = true;
441 });
442 this.on('dragmove', (e) => {
443 this.update();
444 });
445 }
446 _handleMouseDown(e) {
447 if (this._transforming) {
448 return;
449 }
450 this._movingAnchorName = e.target.name().split(' ')[0];
451 var attrs = this._getNodeRect();
452 var width = attrs.width;
453 var height = attrs.height;
454 var hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
455 this.sin = Math.abs(height / hypotenuse);
456 this.cos = Math.abs(width / hypotenuse);
457 if (typeof window !== 'undefined') {
458 window.addEventListener('mousemove', this._handleMouseMove);
459 window.addEventListener('touchmove', this._handleMouseMove);
460 window.addEventListener('mouseup', this._handleMouseUp, true);
461 window.addEventListener('touchend', this._handleMouseUp, true);
462 }
463 this._transforming = true;
464 var ap = e.target.getAbsolutePosition();
465 var pos = e.target.getStage().getPointerPosition();
466 this._anchorDragOffset = {
467 x: pos.x - ap.x,
468 y: pos.y - ap.y,
469 };
470 activeTransformersCount++;
471 this._fire('transformstart', { evt: e.evt, target: this.getNode() });
472 this._nodes.forEach((target) => {
473 target._fire('transformstart', { evt: e.evt, target });
474 });
475 }
476 _handleMouseMove(e) {
477 var x, y, newHypotenuse;
478 var anchorNode = this.findOne('.' + this._movingAnchorName);
479 var stage = anchorNode.getStage();
480 stage.setPointersPositions(e);
481 const pp = stage.getPointerPosition();
482 let newNodePos = {
483 x: pp.x - this._anchorDragOffset.x,
484 y: pp.y - this._anchorDragOffset.y,
485 };
486 const oldAbs = anchorNode.getAbsolutePosition();
487 if (this.anchorDragBoundFunc()) {
488 newNodePos = this.anchorDragBoundFunc()(oldAbs, newNodePos, e);
489 }
490 anchorNode.setAbsolutePosition(newNodePos);
491 const newAbs = anchorNode.getAbsolutePosition();
492 if (oldAbs.x === newAbs.x && oldAbs.y === newAbs.y) {
493 return;
494 }
495 if (this._movingAnchorName === 'rotater') {
496 var attrs = this._getNodeRect();
497 x = anchorNode.x() - attrs.width / 2;
498 y = -anchorNode.y() + attrs.height / 2;
499 let delta = Math.atan2(-y, x) + Math.PI / 2;
500 if (attrs.height < 0) {
501 delta -= Math.PI;
502 }
503 var oldRotation = Global_1.Konva.getAngle(this.rotation());
504 const newRotation = oldRotation + delta;
505 const tol = Global_1.Konva.getAngle(this.rotationSnapTolerance());
506 const snappedRot = getSnap(this.rotationSnaps(), newRotation, tol);
507 const diff = snappedRot - attrs.rotation;
508 const shape = rotateAroundCenter(attrs, diff);
509 this._fitNodesInto(shape, e);
510 return;
511 }
512 var shiftBehavior = this.shiftBehavior();
513 var keepProportion;
514 if (shiftBehavior === 'inverted') {
515 keepProportion = this.keepRatio() && !e.shiftKey;
516 }
517 else if (shiftBehavior === 'none') {
518 keepProportion = this.keepRatio();
519 }
520 else {
521 keepProportion = this.keepRatio() || e.shiftKey;
522 }
523 var centeredScaling = this.centeredScaling() || e.altKey;
524 if (this._movingAnchorName === 'top-left') {
525 if (keepProportion) {
526 var comparePoint = centeredScaling
527 ? {
528 x: this.width() / 2,
529 y: this.height() / 2,
530 }
531 : {
532 x: this.findOne('.bottom-right').x(),
533 y: this.findOne('.bottom-right').y(),
534 };
535 newHypotenuse = Math.sqrt(Math.pow(comparePoint.x - anchorNode.x(), 2) +
536 Math.pow(comparePoint.y - anchorNode.y(), 2));
537 var reverseX = this.findOne('.top-left').x() > comparePoint.x ? -1 : 1;
538 var reverseY = this.findOne('.top-left').y() > comparePoint.y ? -1 : 1;
539 x = newHypotenuse * this.cos * reverseX;
540 y = newHypotenuse * this.sin * reverseY;
541 this.findOne('.top-left').x(comparePoint.x - x);
542 this.findOne('.top-left').y(comparePoint.y - y);
543 }
544 }
545 else if (this._movingAnchorName === 'top-center') {
546 this.findOne('.top-left').y(anchorNode.y());
547 }
548 else if (this._movingAnchorName === 'top-right') {
549 if (keepProportion) {
550 var comparePoint = centeredScaling
551 ? {
552 x: this.width() / 2,
553 y: this.height() / 2,
554 }
555 : {
556 x: this.findOne('.bottom-left').x(),
557 y: this.findOne('.bottom-left').y(),
558 };
559 newHypotenuse = Math.sqrt(Math.pow(anchorNode.x() - comparePoint.x, 2) +
560 Math.pow(comparePoint.y - anchorNode.y(), 2));
561 var reverseX = this.findOne('.top-right').x() < comparePoint.x ? -1 : 1;
562 var reverseY = this.findOne('.top-right').y() > comparePoint.y ? -1 : 1;
563 x = newHypotenuse * this.cos * reverseX;
564 y = newHypotenuse * this.sin * reverseY;
565 this.findOne('.top-right').x(comparePoint.x + x);
566 this.findOne('.top-right').y(comparePoint.y - y);
567 }
568 var pos = anchorNode.position();
569 this.findOne('.top-left').y(pos.y);
570 this.findOne('.bottom-right').x(pos.x);
571 }
572 else if (this._movingAnchorName === 'middle-left') {
573 this.findOne('.top-left').x(anchorNode.x());
574 }
575 else if (this._movingAnchorName === 'middle-right') {
576 this.findOne('.bottom-right').x(anchorNode.x());
577 }
578 else if (this._movingAnchorName === 'bottom-left') {
579 if (keepProportion) {
580 var comparePoint = centeredScaling
581 ? {
582 x: this.width() / 2,
583 y: this.height() / 2,
584 }
585 : {
586 x: this.findOne('.top-right').x(),
587 y: this.findOne('.top-right').y(),
588 };
589 newHypotenuse = Math.sqrt(Math.pow(comparePoint.x - anchorNode.x(), 2) +
590 Math.pow(anchorNode.y() - comparePoint.y, 2));
591 var reverseX = comparePoint.x < anchorNode.x() ? -1 : 1;
592 var reverseY = anchorNode.y() < comparePoint.y ? -1 : 1;
593 x = newHypotenuse * this.cos * reverseX;
594 y = newHypotenuse * this.sin * reverseY;
595 anchorNode.x(comparePoint.x - x);
596 anchorNode.y(comparePoint.y + y);
597 }
598 pos = anchorNode.position();
599 this.findOne('.top-left').x(pos.x);
600 this.findOne('.bottom-right').y(pos.y);
601 }
602 else if (this._movingAnchorName === 'bottom-center') {
603 this.findOne('.bottom-right').y(anchorNode.y());
604 }
605 else if (this._movingAnchorName === 'bottom-right') {
606 if (keepProportion) {
607 var comparePoint = centeredScaling
608 ? {
609 x: this.width() / 2,
610 y: this.height() / 2,
611 }
612 : {
613 x: this.findOne('.top-left').x(),
614 y: this.findOne('.top-left').y(),
615 };
616 newHypotenuse = Math.sqrt(Math.pow(anchorNode.x() - comparePoint.x, 2) +
617 Math.pow(anchorNode.y() - comparePoint.y, 2));
618 var reverseX = this.findOne('.bottom-right').x() < comparePoint.x ? -1 : 1;
619 var reverseY = this.findOne('.bottom-right').y() < comparePoint.y ? -1 : 1;
620 x = newHypotenuse * this.cos * reverseX;
621 y = newHypotenuse * this.sin * reverseY;
622 this.findOne('.bottom-right').x(comparePoint.x + x);
623 this.findOne('.bottom-right').y(comparePoint.y + y);
624 }
625 }
626 else {
627 console.error(new Error('Wrong position argument of selection resizer: ' +
628 this._movingAnchorName));
629 }
630 var centeredScaling = this.centeredScaling() || e.altKey;
631 if (centeredScaling) {
632 var topLeft = this.findOne('.top-left');
633 var bottomRight = this.findOne('.bottom-right');
634 var topOffsetX = topLeft.x();
635 var topOffsetY = topLeft.y();
636 var bottomOffsetX = this.getWidth() - bottomRight.x();
637 var bottomOffsetY = this.getHeight() - bottomRight.y();
638 bottomRight.move({
639 x: -topOffsetX,
640 y: -topOffsetY,
641 });
642 topLeft.move({
643 x: bottomOffsetX,
644 y: bottomOffsetY,
645 });
646 }
647 var absPos = this.findOne('.top-left').getAbsolutePosition();
648 x = absPos.x;
649 y = absPos.y;
650 var width = this.findOne('.bottom-right').x() - this.findOne('.top-left').x();
651 var height = this.findOne('.bottom-right').y() - this.findOne('.top-left').y();
652 this._fitNodesInto({
653 x: x,
654 y: y,
655 width: width,
656 height: height,
657 rotation: Global_1.Konva.getAngle(this.rotation()),
658 }, e);
659 }
660 _handleMouseUp(e) {
661 this._removeEvents(e);
662 }
663 getAbsoluteTransform() {
664 return this.getTransform();
665 }
666 _removeEvents(e) {
667 var _a;
668 if (this._transforming) {
669 this._transforming = false;
670 if (typeof window !== 'undefined') {
671 window.removeEventListener('mousemove', this._handleMouseMove);
672 window.removeEventListener('touchmove', this._handleMouseMove);
673 window.removeEventListener('mouseup', this._handleMouseUp, true);
674 window.removeEventListener('touchend', this._handleMouseUp, true);
675 }
676 var node = this.getNode();
677 activeTransformersCount--;
678 this._fire('transformend', { evt: e, target: node });
679 (_a = this.getLayer()) === null || _a === void 0 ? void 0 : _a.batchDraw();
680 if (node) {
681 this._nodes.forEach((target) => {
682 var _a;
683 target._fire('transformend', { evt: e, target });
684 (_a = target.getLayer()) === null || _a === void 0 ? void 0 : _a.batchDraw();
685 });
686 }
687 this._movingAnchorName = null;
688 }
689 }
690 _fitNodesInto(newAttrs, evt) {
691 var oldAttrs = this._getNodeRect();
692 const minSize = 1;
693 if (Util_1.Util._inRange(newAttrs.width, -this.padding() * 2 - minSize, minSize)) {
694 this.update();
695 return;
696 }
697 if (Util_1.Util._inRange(newAttrs.height, -this.padding() * 2 - minSize, minSize)) {
698 this.update();
699 return;
700 }
701 var t = new Util_1.Transform();
702 t.rotate(Global_1.Konva.getAngle(this.rotation()));
703 if (this._movingAnchorName &&
704 newAttrs.width < 0 &&
705 this._movingAnchorName.indexOf('left') >= 0) {
706 const offset = t.point({
707 x: -this.padding() * 2,
708 y: 0,
709 });
710 newAttrs.x += offset.x;
711 newAttrs.y += offset.y;
712 newAttrs.width += this.padding() * 2;
713 this._movingAnchorName = this._movingAnchorName.replace('left', 'right');
714 this._anchorDragOffset.x -= offset.x;
715 this._anchorDragOffset.y -= offset.y;
716 }
717 else if (this._movingAnchorName &&
718 newAttrs.width < 0 &&
719 this._movingAnchorName.indexOf('right') >= 0) {
720 const offset = t.point({
721 x: this.padding() * 2,
722 y: 0,
723 });
724 this._movingAnchorName = this._movingAnchorName.replace('right', 'left');
725 this._anchorDragOffset.x -= offset.x;
726 this._anchorDragOffset.y -= offset.y;
727 newAttrs.width += this.padding() * 2;
728 }
729 if (this._movingAnchorName &&
730 newAttrs.height < 0 &&
731 this._movingAnchorName.indexOf('top') >= 0) {
732 const offset = t.point({
733 x: 0,
734 y: -this.padding() * 2,
735 });
736 newAttrs.x += offset.x;
737 newAttrs.y += offset.y;
738 this._movingAnchorName = this._movingAnchorName.replace('top', 'bottom');
739 this._anchorDragOffset.x -= offset.x;
740 this._anchorDragOffset.y -= offset.y;
741 newAttrs.height += this.padding() * 2;
742 }
743 else if (this._movingAnchorName &&
744 newAttrs.height < 0 &&
745 this._movingAnchorName.indexOf('bottom') >= 0) {
746 const offset = t.point({
747 x: 0,
748 y: this.padding() * 2,
749 });
750 this._movingAnchorName = this._movingAnchorName.replace('bottom', 'top');
751 this._anchorDragOffset.x -= offset.x;
752 this._anchorDragOffset.y -= offset.y;
753 newAttrs.height += this.padding() * 2;
754 }
755 if (this.boundBoxFunc()) {
756 const bounded = this.boundBoxFunc()(oldAttrs, newAttrs);
757 if (bounded) {
758 newAttrs = bounded;
759 }
760 else {
761 Util_1.Util.warn('boundBoxFunc returned falsy. You should return new bound rect from it!');
762 }
763 }
764 const baseSize = 10000000;
765 const oldTr = new Util_1.Transform();
766 oldTr.translate(oldAttrs.x, oldAttrs.y);
767 oldTr.rotate(oldAttrs.rotation);
768 oldTr.scale(oldAttrs.width / baseSize, oldAttrs.height / baseSize);
769 const newTr = new Util_1.Transform();
770 const newScaleX = newAttrs.width / baseSize;
771 const newScaleY = newAttrs.height / baseSize;
772 if (this.flipEnabled() === false) {
773 newTr.translate(newAttrs.x, newAttrs.y);
774 newTr.rotate(newAttrs.rotation);
775 newTr.translate(newAttrs.width < 0 ? newAttrs.width : 0, newAttrs.height < 0 ? newAttrs.height : 0);
776 newTr.scale(Math.abs(newScaleX), Math.abs(newScaleY));
777 }
778 else {
779 newTr.translate(newAttrs.x, newAttrs.y);
780 newTr.rotate(newAttrs.rotation);
781 newTr.scale(newScaleX, newScaleY);
782 }
783 const delta = newTr.multiply(oldTr.invert());
784 this._nodes.forEach((node) => {
785 var _a;
786 const parentTransform = node.getParent().getAbsoluteTransform();
787 const localTransform = node.getTransform().copy();
788 localTransform.translate(node.offsetX(), node.offsetY());
789 const newLocalTransform = new Util_1.Transform();
790 newLocalTransform
791 .multiply(parentTransform.copy().invert())
792 .multiply(delta)
793 .multiply(parentTransform)
794 .multiply(localTransform);
795 const attrs = newLocalTransform.decompose();
796 node.setAttrs(attrs);
797 (_a = node.getLayer()) === null || _a === void 0 ? void 0 : _a.batchDraw();
798 });
799 this.rotation(Util_1.Util._getRotation(newAttrs.rotation));
800 this._nodes.forEach((node) => {
801 this._fire('transform', { evt: evt, target: node });
802 node._fire('transform', { evt: evt, target: node });
803 });
804 this._resetTransformCache();
805 this.update();
806 this.getLayer().batchDraw();
807 }
808 forceUpdate() {
809 this._resetTransformCache();
810 this.update();
811 }
812 _batchChangeChild(selector, attrs) {
813 const anchor = this.findOne(selector);
814 anchor.setAttrs(attrs);
815 }
816 update() {
817 var _a;
818 var attrs = this._getNodeRect();
819 this.rotation(Util_1.Util._getRotation(attrs.rotation));
820 var width = attrs.width;
821 var height = attrs.height;
822 var enabledAnchors = this.enabledAnchors();
823 var resizeEnabled = this.resizeEnabled();
824 var padding = this.padding();
825 var anchorSize = this.anchorSize();
826 const anchors = this.find('._anchor');
827 anchors.forEach((node) => {
828 node.setAttrs({
829 width: anchorSize,
830 height: anchorSize,
831 offsetX: anchorSize / 2,
832 offsetY: anchorSize / 2,
833 stroke: this.anchorStroke(),
834 strokeWidth: this.anchorStrokeWidth(),
835 fill: this.anchorFill(),
836 cornerRadius: this.anchorCornerRadius(),
837 });
838 });
839 this._batchChangeChild('.top-left', {
840 x: 0,
841 y: 0,
842 offsetX: anchorSize / 2 + padding,
843 offsetY: anchorSize / 2 + padding,
844 visible: resizeEnabled && enabledAnchors.indexOf('top-left') >= 0,
845 });
846 this._batchChangeChild('.top-center', {
847 x: width / 2,
848 y: 0,
849 offsetY: anchorSize / 2 + padding,
850 visible: resizeEnabled && enabledAnchors.indexOf('top-center') >= 0,
851 });
852 this._batchChangeChild('.top-right', {
853 x: width,
854 y: 0,
855 offsetX: anchorSize / 2 - padding,
856 offsetY: anchorSize / 2 + padding,
857 visible: resizeEnabled && enabledAnchors.indexOf('top-right') >= 0,
858 });
859 this._batchChangeChild('.middle-left', {
860 x: 0,
861 y: height / 2,
862 offsetX: anchorSize / 2 + padding,
863 visible: resizeEnabled && enabledAnchors.indexOf('middle-left') >= 0,
864 });
865 this._batchChangeChild('.middle-right', {
866 x: width,
867 y: height / 2,
868 offsetX: anchorSize / 2 - padding,
869 visible: resizeEnabled && enabledAnchors.indexOf('middle-right') >= 0,
870 });
871 this._batchChangeChild('.bottom-left', {
872 x: 0,
873 y: height,
874 offsetX: anchorSize / 2 + padding,
875 offsetY: anchorSize / 2 - padding,
876 visible: resizeEnabled && enabledAnchors.indexOf('bottom-left') >= 0,
877 });
878 this._batchChangeChild('.bottom-center', {
879 x: width / 2,
880 y: height,
881 offsetY: anchorSize / 2 - padding,
882 visible: resizeEnabled && enabledAnchors.indexOf('bottom-center') >= 0,
883 });
884 this._batchChangeChild('.bottom-right', {
885 x: width,
886 y: height,
887 offsetX: anchorSize / 2 - padding,
888 offsetY: anchorSize / 2 - padding,
889 visible: resizeEnabled && enabledAnchors.indexOf('bottom-right') >= 0,
890 });
891 this._batchChangeChild('.rotater', {
892 x: width / 2,
893 y: -this.rotateAnchorOffset() * Util_1.Util._sign(height) - padding,
894 visible: this.rotateEnabled(),
895 });
896 this._batchChangeChild('.back', {
897 width: width,
898 height: height,
899 visible: this.borderEnabled(),
900 stroke: this.borderStroke(),
901 strokeWidth: this.borderStrokeWidth(),
902 dash: this.borderDash(),
903 x: 0,
904 y: 0,
905 });
906 const styleFunc = this.anchorStyleFunc();
907 if (styleFunc) {
908 anchors.forEach((node) => {
909 styleFunc(node);
910 });
911 }
912 (_a = this.getLayer()) === null || _a === void 0 ? void 0 : _a.batchDraw();
913 }
914 isTransforming() {
915 return this._transforming;
916 }
917 stopTransform() {
918 if (this._transforming) {
919 this._removeEvents();
920 var anchorNode = this.findOne('.' + this._movingAnchorName);
921 if (anchorNode) {
922 anchorNode.stopDrag();
923 }
924 }
925 }
926 destroy() {
927 if (this.getStage() && this._cursorChange) {
928 this.getStage().content && (this.getStage().content.style.cursor = '');
929 }
930 Group_1.Group.prototype.destroy.call(this);
931 this.detach();
932 this._removeEvents();
933 return this;
934 }
935 toObject() {
936 return Node_1.Node.prototype.toObject.call(this);
937 }
938 clone(obj) {
939 var node = Node_1.Node.prototype.clone.call(this, obj);
940 return node;
941 }
942 getClientRect() {
943 if (this.nodes().length > 0) {
944 return super.getClientRect();
945 }
946 else {
947 return { x: 0, y: 0, width: 0, height: 0 };
948 }
949 }
950}
951exports.Transformer = Transformer;
952Transformer.isTransforming = () => {
953 return activeTransformersCount > 0;
954};
955function validateAnchors(val) {
956 if (!(val instanceof Array)) {
957 Util_1.Util.warn('enabledAnchors value should be an array');
958 }
959 if (val instanceof Array) {
960 val.forEach(function (name) {
961 if (ANCHORS_NAMES.indexOf(name) === -1) {
962 Util_1.Util.warn('Unknown anchor name: ' +
963 name +
964 '. Available names are: ' +
965 ANCHORS_NAMES.join(', '));
966 }
967 });
968 }
969 return val || [];
970}
971Transformer.prototype.className = 'Transformer';
972(0, Global_2._registerNode)(Transformer);
973Factory_1.Factory.addGetterSetter(Transformer, 'enabledAnchors', ANCHORS_NAMES, validateAnchors);
974Factory_1.Factory.addGetterSetter(Transformer, 'flipEnabled', true, (0, Validators_1.getBooleanValidator)());
975Factory_1.Factory.addGetterSetter(Transformer, 'resizeEnabled', true);
976Factory_1.Factory.addGetterSetter(Transformer, 'anchorSize', 10, (0, Validators_1.getNumberValidator)());
977Factory_1.Factory.addGetterSetter(Transformer, 'rotateEnabled', true);
978Factory_1.Factory.addGetterSetter(Transformer, 'rotateLineVisible', true);
979Factory_1.Factory.addGetterSetter(Transformer, 'rotationSnaps', []);
980Factory_1.Factory.addGetterSetter(Transformer, 'rotateAnchorOffset', 50, (0, Validators_1.getNumberValidator)());
981Factory_1.Factory.addGetterSetter(Transformer, 'rotateAnchorCursor', 'crosshair');
982Factory_1.Factory.addGetterSetter(Transformer, 'rotationSnapTolerance', 5, (0, Validators_1.getNumberValidator)());
983Factory_1.Factory.addGetterSetter(Transformer, 'borderEnabled', true);
984Factory_1.Factory.addGetterSetter(Transformer, 'anchorStroke', 'rgb(0, 161, 255)');
985Factory_1.Factory.addGetterSetter(Transformer, 'anchorStrokeWidth', 1, (0, Validators_1.getNumberValidator)());
986Factory_1.Factory.addGetterSetter(Transformer, 'anchorFill', 'white');
987Factory_1.Factory.addGetterSetter(Transformer, 'anchorCornerRadius', 0, (0, Validators_1.getNumberValidator)());
988Factory_1.Factory.addGetterSetter(Transformer, 'borderStroke', 'rgb(0, 161, 255)');
989Factory_1.Factory.addGetterSetter(Transformer, 'borderStrokeWidth', 1, (0, Validators_1.getNumberValidator)());
990Factory_1.Factory.addGetterSetter(Transformer, 'borderDash');
991Factory_1.Factory.addGetterSetter(Transformer, 'keepRatio', true);
992Factory_1.Factory.addGetterSetter(Transformer, 'shiftBehavior', 'default');
993Factory_1.Factory.addGetterSetter(Transformer, 'centeredScaling', false);
994Factory_1.Factory.addGetterSetter(Transformer, 'ignoreStroke', false);
995Factory_1.Factory.addGetterSetter(Transformer, 'padding', 0, (0, Validators_1.getNumberValidator)());
996Factory_1.Factory.addGetterSetter(Transformer, 'node');
997Factory_1.Factory.addGetterSetter(Transformer, 'nodes');
998Factory_1.Factory.addGetterSetter(Transformer, 'boundBoxFunc');
999Factory_1.Factory.addGetterSetter(Transformer, 'anchorDragBoundFunc');
1000Factory_1.Factory.addGetterSetter(Transformer, 'anchorStyleFunc');
1001Factory_1.Factory.addGetterSetter(Transformer, 'shouldOverdrawWholeArea', false);
1002Factory_1.Factory.addGetterSetter(Transformer, 'useSingleNodeRotation', true);
1003Factory_1.Factory.backCompat(Transformer, {
1004 lineEnabled: 'borderEnabled',
1005 rotateHandlerOffset: 'rotateAnchorOffset',
1006 enabledHandlers: 'enabledAnchors',
1007});
Note: See TracBrowser for help on using the repository browser.