"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Transformer = void 0; const Util_1 = require("../Util"); const Factory_1 = require("../Factory"); const Node_1 = require("../Node"); const Shape_1 = require("../Shape"); const Rect_1 = require("./Rect"); const Group_1 = require("../Group"); const Global_1 = require("../Global"); const Validators_1 = require("../Validators"); const Global_2 = require("../Global"); var EVENTS_NAME = 'tr-konva'; var ATTR_CHANGE_LIST = [ 'resizeEnabledChange', 'rotateAnchorOffsetChange', 'rotateEnabledChange', 'enabledAnchorsChange', 'anchorSizeChange', 'borderEnabledChange', 'borderStrokeChange', 'borderStrokeWidthChange', 'borderDashChange', 'anchorStrokeChange', 'anchorStrokeWidthChange', 'anchorFillChange', 'anchorCornerRadiusChange', 'ignoreStrokeChange', 'anchorStyleFuncChange', ] .map((e) => e + `.${EVENTS_NAME}`) .join(' '); var NODES_RECT = 'nodesRect'; var TRANSFORM_CHANGE_STR = [ 'widthChange', 'heightChange', 'scaleXChange', 'scaleYChange', 'skewXChange', 'skewYChange', 'rotationChange', 'offsetXChange', 'offsetYChange', 'transformsEnabledChange', 'strokeWidthChange', ]; var ANGLES = { 'top-left': -45, 'top-center': 0, 'top-right': 45, 'middle-right': -90, 'middle-left': 90, 'bottom-left': -135, 'bottom-center': 180, 'bottom-right': 135, }; const TOUCH_DEVICE = 'ontouchstart' in Global_1.Konva._global; function getCursor(anchorName, rad, rotateCursor) { if (anchorName === 'rotater') { return rotateCursor; } rad += Util_1.Util.degToRad(ANGLES[anchorName] || 0); var angle = ((Util_1.Util.radToDeg(rad) % 360) + 360) % 360; if (Util_1.Util._inRange(angle, 315 + 22.5, 360) || Util_1.Util._inRange(angle, 0, 22.5)) { return 'ns-resize'; } else if (Util_1.Util._inRange(angle, 45 - 22.5, 45 + 22.5)) { return 'nesw-resize'; } else if (Util_1.Util._inRange(angle, 90 - 22.5, 90 + 22.5)) { return 'ew-resize'; } else if (Util_1.Util._inRange(angle, 135 - 22.5, 135 + 22.5)) { return 'nwse-resize'; } else if (Util_1.Util._inRange(angle, 180 - 22.5, 180 + 22.5)) { return 'ns-resize'; } else if (Util_1.Util._inRange(angle, 225 - 22.5, 225 + 22.5)) { return 'nesw-resize'; } else if (Util_1.Util._inRange(angle, 270 - 22.5, 270 + 22.5)) { return 'ew-resize'; } else if (Util_1.Util._inRange(angle, 315 - 22.5, 315 + 22.5)) { return 'nwse-resize'; } else { Util_1.Util.error('Transformer has unknown angle for cursor detection: ' + angle); return 'pointer'; } } var ANCHORS_NAMES = [ 'top-left', 'top-center', 'top-right', 'middle-right', 'middle-left', 'bottom-left', 'bottom-center', 'bottom-right', ]; var MAX_SAFE_INTEGER = 100000000; function getCenter(shape) { return { x: shape.x + (shape.width / 2) * Math.cos(shape.rotation) + (shape.height / 2) * Math.sin(-shape.rotation), y: shape.y + (shape.height / 2) * Math.cos(shape.rotation) + (shape.width / 2) * Math.sin(shape.rotation), }; } function rotateAroundPoint(shape, angleRad, point) { const x = point.x + (shape.x - point.x) * Math.cos(angleRad) - (shape.y - point.y) * Math.sin(angleRad); const y = point.y + (shape.x - point.x) * Math.sin(angleRad) + (shape.y - point.y) * Math.cos(angleRad); return { ...shape, rotation: shape.rotation + angleRad, x, y, }; } function rotateAroundCenter(shape, deltaRad) { const center = getCenter(shape); return rotateAroundPoint(shape, deltaRad, center); } function getSnap(snaps, newRotationRad, tol) { let snapped = newRotationRad; for (let i = 0; i < snaps.length; i++) { const angle = Global_1.Konva.getAngle(snaps[i]); const absDiff = Math.abs(angle - newRotationRad) % (Math.PI * 2); const dif = Math.min(absDiff, Math.PI * 2 - absDiff); if (dif < tol) { snapped = angle; } } return snapped; } let activeTransformersCount = 0; class Transformer extends Group_1.Group { constructor(config) { super(config); this._movingAnchorName = null; this._transforming = false; this._createElements(); this._handleMouseMove = this._handleMouseMove.bind(this); this._handleMouseUp = this._handleMouseUp.bind(this); this.update = this.update.bind(this); this.on(ATTR_CHANGE_LIST, this.update); if (this.getNode()) { this.update(); } } attachTo(node) { this.setNode(node); return this; } setNode(node) { Util_1.Util.warn('tr.setNode(shape), tr.node(shape) and tr.attachTo(shape) methods are deprecated. Please use tr.nodes(nodesArray) instead.'); return this.setNodes([node]); } getNode() { return this._nodes && this._nodes[0]; } _getEventNamespace() { return EVENTS_NAME + this._id; } setNodes(nodes = []) { if (this._nodes && this._nodes.length) { this.detach(); } const filteredNodes = nodes.filter((node) => { if (node.isAncestorOf(this)) { Util_1.Util.error('Konva.Transformer cannot be an a child of the node you are trying to attach'); return false; } return true; }); this._nodes = nodes = filteredNodes; if (nodes.length === 1 && this.useSingleNodeRotation()) { this.rotation(nodes[0].getAbsoluteRotation()); } else { this.rotation(0); } this._nodes.forEach((node) => { const onChange = () => { if (this.nodes().length === 1 && this.useSingleNodeRotation()) { this.rotation(this.nodes()[0].getAbsoluteRotation()); } this._resetTransformCache(); if (!this._transforming && !this.isDragging()) { this.update(); } }; const additionalEvents = node._attrsAffectingSize .map((prop) => prop + 'Change.' + this._getEventNamespace()) .join(' '); node.on(additionalEvents, onChange); node.on(TRANSFORM_CHANGE_STR.map((e) => e + `.${this._getEventNamespace()}`).join(' '), onChange); node.on(`absoluteTransformChange.${this._getEventNamespace()}`, onChange); this._proxyDrag(node); }); this._resetTransformCache(); var elementsCreated = !!this.findOne('.top-left'); if (elementsCreated) { this.update(); } return this; } _proxyDrag(node) { let lastPos; node.on(`dragstart.${this._getEventNamespace()}`, (e) => { lastPos = node.getAbsolutePosition(); if (!this.isDragging() && node !== this.findOne('.back')) { this.startDrag(e, false); } }); node.on(`dragmove.${this._getEventNamespace()}`, (e) => { if (!lastPos) { return; } const abs = node.getAbsolutePosition(); const dx = abs.x - lastPos.x; const dy = abs.y - lastPos.y; this.nodes().forEach((otherNode) => { if (otherNode === node) { return; } if (otherNode.isDragging()) { return; } const otherAbs = otherNode.getAbsolutePosition(); otherNode.setAbsolutePosition({ x: otherAbs.x + dx, y: otherAbs.y + dy, }); otherNode.startDrag(e); }); lastPos = null; }); } getNodes() { return this._nodes || []; } getActiveAnchor() { return this._movingAnchorName; } detach() { if (this._nodes) { this._nodes.forEach((node) => { node.off('.' + this._getEventNamespace()); }); } this._nodes = []; this._resetTransformCache(); } _resetTransformCache() { this._clearCache(NODES_RECT); this._clearCache('transform'); this._clearSelfAndDescendantCache('absoluteTransform'); } _getNodeRect() { return this._getCache(NODES_RECT, this.__getNodeRect); } __getNodeShape(node, rot = this.rotation(), relative) { var rect = node.getClientRect({ skipTransform: true, skipShadow: true, skipStroke: this.ignoreStroke(), }); var absScale = node.getAbsoluteScale(relative); var absPos = node.getAbsolutePosition(relative); var dx = rect.x * absScale.x - node.offsetX() * absScale.x; var dy = rect.y * absScale.y - node.offsetY() * absScale.y; const rotation = (Global_1.Konva.getAngle(node.getAbsoluteRotation()) + Math.PI * 2) % (Math.PI * 2); const box = { x: absPos.x + dx * Math.cos(rotation) + dy * Math.sin(-rotation), y: absPos.y + dy * Math.cos(rotation) + dx * Math.sin(rotation), width: rect.width * absScale.x, height: rect.height * absScale.y, rotation: rotation, }; return rotateAroundPoint(box, -Global_1.Konva.getAngle(rot), { x: 0, y: 0, }); } __getNodeRect() { var node = this.getNode(); if (!node) { return { x: -MAX_SAFE_INTEGER, y: -MAX_SAFE_INTEGER, width: 0, height: 0, rotation: 0, }; } const totalPoints = []; this.nodes().map((node) => { const box = node.getClientRect({ skipTransform: true, skipShadow: true, skipStroke: this.ignoreStroke(), }); var points = [ { x: box.x, y: box.y }, { x: box.x + box.width, y: box.y }, { x: box.x + box.width, y: box.y + box.height }, { x: box.x, y: box.y + box.height }, ]; var trans = node.getAbsoluteTransform(); points.forEach(function (point) { var transformed = trans.point(point); totalPoints.push(transformed); }); }); const tr = new Util_1.Transform(); tr.rotate(-Global_1.Konva.getAngle(this.rotation())); var minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; totalPoints.forEach(function (point) { var transformed = tr.point(point); if (minX === undefined) { minX = maxX = transformed.x; minY = maxY = transformed.y; } minX = Math.min(minX, transformed.x); minY = Math.min(minY, transformed.y); maxX = Math.max(maxX, transformed.x); maxY = Math.max(maxY, transformed.y); }); tr.invert(); const p = tr.point({ x: minX, y: minY }); return { x: p.x, y: p.y, width: maxX - minX, height: maxY - minY, rotation: Global_1.Konva.getAngle(this.rotation()), }; } getX() { return this._getNodeRect().x; } getY() { return this._getNodeRect().y; } getWidth() { return this._getNodeRect().width; } getHeight() { return this._getNodeRect().height; } _createElements() { this._createBack(); ANCHORS_NAMES.forEach((name) => { this._createAnchor(name); }); this._createAnchor('rotater'); } _createAnchor(name) { var anchor = new Rect_1.Rect({ stroke: 'rgb(0, 161, 255)', fill: 'white', strokeWidth: 1, name: name + ' _anchor', dragDistance: 0, draggable: true, hitStrokeWidth: TOUCH_DEVICE ? 10 : 'auto', }); var self = this; anchor.on('mousedown touchstart', function (e) { self._handleMouseDown(e); }); anchor.on('dragstart', (e) => { anchor.stopDrag(); e.cancelBubble = true; }); anchor.on('dragend', (e) => { e.cancelBubble = true; }); anchor.on('mouseenter', () => { var rad = Global_1.Konva.getAngle(this.rotation()); var rotateCursor = this.rotateAnchorCursor(); var cursor = getCursor(name, rad, rotateCursor); anchor.getStage().content && (anchor.getStage().content.style.cursor = cursor); this._cursorChange = true; }); anchor.on('mouseout', () => { anchor.getStage().content && (anchor.getStage().content.style.cursor = ''); this._cursorChange = false; }); this.add(anchor); } _createBack() { var back = new Shape_1.Shape({ name: 'back', width: 0, height: 0, draggable: true, sceneFunc(ctx, shape) { var tr = shape.getParent(); var padding = tr.padding(); ctx.beginPath(); ctx.rect(-padding, -padding, shape.width() + padding * 2, shape.height() + padding * 2); ctx.moveTo(shape.width() / 2, -padding); if (tr.rotateEnabled() && tr.rotateLineVisible()) { ctx.lineTo(shape.width() / 2, -tr.rotateAnchorOffset() * Util_1.Util._sign(shape.height()) - padding); } ctx.fillStrokeShape(shape); }, hitFunc: (ctx, shape) => { if (!this.shouldOverdrawWholeArea()) { return; } var padding = this.padding(); ctx.beginPath(); ctx.rect(-padding, -padding, shape.width() + padding * 2, shape.height() + padding * 2); ctx.fillStrokeShape(shape); }, }); this.add(back); this._proxyDrag(back); back.on('dragstart', (e) => { e.cancelBubble = true; }); back.on('dragmove', (e) => { e.cancelBubble = true; }); back.on('dragend', (e) => { e.cancelBubble = true; }); this.on('dragmove', (e) => { this.update(); }); } _handleMouseDown(e) { if (this._transforming) { return; } this._movingAnchorName = e.target.name().split(' ')[0]; var attrs = this._getNodeRect(); var width = attrs.width; var height = attrs.height; var hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); this.sin = Math.abs(height / hypotenuse); this.cos = Math.abs(width / hypotenuse); if (typeof window !== 'undefined') { window.addEventListener('mousemove', this._handleMouseMove); window.addEventListener('touchmove', this._handleMouseMove); window.addEventListener('mouseup', this._handleMouseUp, true); window.addEventListener('touchend', this._handleMouseUp, true); } this._transforming = true; var ap = e.target.getAbsolutePosition(); var pos = e.target.getStage().getPointerPosition(); this._anchorDragOffset = { x: pos.x - ap.x, y: pos.y - ap.y, }; activeTransformersCount++; this._fire('transformstart', { evt: e.evt, target: this.getNode() }); this._nodes.forEach((target) => { target._fire('transformstart', { evt: e.evt, target }); }); } _handleMouseMove(e) { var x, y, newHypotenuse; var anchorNode = this.findOne('.' + this._movingAnchorName); var stage = anchorNode.getStage(); stage.setPointersPositions(e); const pp = stage.getPointerPosition(); let newNodePos = { x: pp.x - this._anchorDragOffset.x, y: pp.y - this._anchorDragOffset.y, }; const oldAbs = anchorNode.getAbsolutePosition(); if (this.anchorDragBoundFunc()) { newNodePos = this.anchorDragBoundFunc()(oldAbs, newNodePos, e); } anchorNode.setAbsolutePosition(newNodePos); const newAbs = anchorNode.getAbsolutePosition(); if (oldAbs.x === newAbs.x && oldAbs.y === newAbs.y) { return; } if (this._movingAnchorName === 'rotater') { var attrs = this._getNodeRect(); x = anchorNode.x() - attrs.width / 2; y = -anchorNode.y() + attrs.height / 2; let delta = Math.atan2(-y, x) + Math.PI / 2; if (attrs.height < 0) { delta -= Math.PI; } var oldRotation = Global_1.Konva.getAngle(this.rotation()); const newRotation = oldRotation + delta; const tol = Global_1.Konva.getAngle(this.rotationSnapTolerance()); const snappedRot = getSnap(this.rotationSnaps(), newRotation, tol); const diff = snappedRot - attrs.rotation; const shape = rotateAroundCenter(attrs, diff); this._fitNodesInto(shape, e); return; } var shiftBehavior = this.shiftBehavior(); var keepProportion; if (shiftBehavior === 'inverted') { keepProportion = this.keepRatio() && !e.shiftKey; } else if (shiftBehavior === 'none') { keepProportion = this.keepRatio(); } else { keepProportion = this.keepRatio() || e.shiftKey; } var centeredScaling = this.centeredScaling() || e.altKey; if (this._movingAnchorName === 'top-left') { if (keepProportion) { var comparePoint = centeredScaling ? { x: this.width() / 2, y: this.height() / 2, } : { x: this.findOne('.bottom-right').x(), y: this.findOne('.bottom-right').y(), }; newHypotenuse = Math.sqrt(Math.pow(comparePoint.x - anchorNode.x(), 2) + Math.pow(comparePoint.y - anchorNode.y(), 2)); var reverseX = this.findOne('.top-left').x() > comparePoint.x ? -1 : 1; var reverseY = this.findOne('.top-left').y() > comparePoint.y ? -1 : 1; x = newHypotenuse * this.cos * reverseX; y = newHypotenuse * this.sin * reverseY; this.findOne('.top-left').x(comparePoint.x - x); this.findOne('.top-left').y(comparePoint.y - y); } } else if (this._movingAnchorName === 'top-center') { this.findOne('.top-left').y(anchorNode.y()); } else if (this._movingAnchorName === 'top-right') { if (keepProportion) { var comparePoint = centeredScaling ? { x: this.width() / 2, y: this.height() / 2, } : { x: this.findOne('.bottom-left').x(), y: this.findOne('.bottom-left').y(), }; newHypotenuse = Math.sqrt(Math.pow(anchorNode.x() - comparePoint.x, 2) + Math.pow(comparePoint.y - anchorNode.y(), 2)); var reverseX = this.findOne('.top-right').x() < comparePoint.x ? -1 : 1; var reverseY = this.findOne('.top-right').y() > comparePoint.y ? -1 : 1; x = newHypotenuse * this.cos * reverseX; y = newHypotenuse * this.sin * reverseY; this.findOne('.top-right').x(comparePoint.x + x); this.findOne('.top-right').y(comparePoint.y - y); } var pos = anchorNode.position(); this.findOne('.top-left').y(pos.y); this.findOne('.bottom-right').x(pos.x); } else if (this._movingAnchorName === 'middle-left') { this.findOne('.top-left').x(anchorNode.x()); } else if (this._movingAnchorName === 'middle-right') { this.findOne('.bottom-right').x(anchorNode.x()); } else if (this._movingAnchorName === 'bottom-left') { if (keepProportion) { var comparePoint = centeredScaling ? { x: this.width() / 2, y: this.height() / 2, } : { x: this.findOne('.top-right').x(), y: this.findOne('.top-right').y(), }; newHypotenuse = Math.sqrt(Math.pow(comparePoint.x - anchorNode.x(), 2) + Math.pow(anchorNode.y() - comparePoint.y, 2)); var reverseX = comparePoint.x < anchorNode.x() ? -1 : 1; var reverseY = anchorNode.y() < comparePoint.y ? -1 : 1; x = newHypotenuse * this.cos * reverseX; y = newHypotenuse * this.sin * reverseY; anchorNode.x(comparePoint.x - x); anchorNode.y(comparePoint.y + y); } pos = anchorNode.position(); this.findOne('.top-left').x(pos.x); this.findOne('.bottom-right').y(pos.y); } else if (this._movingAnchorName === 'bottom-center') { this.findOne('.bottom-right').y(anchorNode.y()); } else if (this._movingAnchorName === 'bottom-right') { if (keepProportion) { var comparePoint = centeredScaling ? { x: this.width() / 2, y: this.height() / 2, } : { x: this.findOne('.top-left').x(), y: this.findOne('.top-left').y(), }; newHypotenuse = Math.sqrt(Math.pow(anchorNode.x() - comparePoint.x, 2) + Math.pow(anchorNode.y() - comparePoint.y, 2)); var reverseX = this.findOne('.bottom-right').x() < comparePoint.x ? -1 : 1; var reverseY = this.findOne('.bottom-right').y() < comparePoint.y ? -1 : 1; x = newHypotenuse * this.cos * reverseX; y = newHypotenuse * this.sin * reverseY; this.findOne('.bottom-right').x(comparePoint.x + x); this.findOne('.bottom-right').y(comparePoint.y + y); } } else { console.error(new Error('Wrong position argument of selection resizer: ' + this._movingAnchorName)); } var centeredScaling = this.centeredScaling() || e.altKey; if (centeredScaling) { var topLeft = this.findOne('.top-left'); var bottomRight = this.findOne('.bottom-right'); var topOffsetX = topLeft.x(); var topOffsetY = topLeft.y(); var bottomOffsetX = this.getWidth() - bottomRight.x(); var bottomOffsetY = this.getHeight() - bottomRight.y(); bottomRight.move({ x: -topOffsetX, y: -topOffsetY, }); topLeft.move({ x: bottomOffsetX, y: bottomOffsetY, }); } var absPos = this.findOne('.top-left').getAbsolutePosition(); x = absPos.x; y = absPos.y; var width = this.findOne('.bottom-right').x() - this.findOne('.top-left').x(); var height = this.findOne('.bottom-right').y() - this.findOne('.top-left').y(); this._fitNodesInto({ x: x, y: y, width: width, height: height, rotation: Global_1.Konva.getAngle(this.rotation()), }, e); } _handleMouseUp(e) { this._removeEvents(e); } getAbsoluteTransform() { return this.getTransform(); } _removeEvents(e) { var _a; if (this._transforming) { this._transforming = false; if (typeof window !== 'undefined') { window.removeEventListener('mousemove', this._handleMouseMove); window.removeEventListener('touchmove', this._handleMouseMove); window.removeEventListener('mouseup', this._handleMouseUp, true); window.removeEventListener('touchend', this._handleMouseUp, true); } var node = this.getNode(); activeTransformersCount--; this._fire('transformend', { evt: e, target: node }); (_a = this.getLayer()) === null || _a === void 0 ? void 0 : _a.batchDraw(); if (node) { this._nodes.forEach((target) => { var _a; target._fire('transformend', { evt: e, target }); (_a = target.getLayer()) === null || _a === void 0 ? void 0 : _a.batchDraw(); }); } this._movingAnchorName = null; } } _fitNodesInto(newAttrs, evt) { var oldAttrs = this._getNodeRect(); const minSize = 1; if (Util_1.Util._inRange(newAttrs.width, -this.padding() * 2 - minSize, minSize)) { this.update(); return; } if (Util_1.Util._inRange(newAttrs.height, -this.padding() * 2 - minSize, minSize)) { this.update(); return; } var t = new Util_1.Transform(); t.rotate(Global_1.Konva.getAngle(this.rotation())); if (this._movingAnchorName && newAttrs.width < 0 && this._movingAnchorName.indexOf('left') >= 0) { const offset = t.point({ x: -this.padding() * 2, y: 0, }); newAttrs.x += offset.x; newAttrs.y += offset.y; newAttrs.width += this.padding() * 2; this._movingAnchorName = this._movingAnchorName.replace('left', 'right'); this._anchorDragOffset.x -= offset.x; this._anchorDragOffset.y -= offset.y; } else if (this._movingAnchorName && newAttrs.width < 0 && this._movingAnchorName.indexOf('right') >= 0) { const offset = t.point({ x: this.padding() * 2, y: 0, }); this._movingAnchorName = this._movingAnchorName.replace('right', 'left'); this._anchorDragOffset.x -= offset.x; this._anchorDragOffset.y -= offset.y; newAttrs.width += this.padding() * 2; } if (this._movingAnchorName && newAttrs.height < 0 && this._movingAnchorName.indexOf('top') >= 0) { const offset = t.point({ x: 0, y: -this.padding() * 2, }); newAttrs.x += offset.x; newAttrs.y += offset.y; this._movingAnchorName = this._movingAnchorName.replace('top', 'bottom'); this._anchorDragOffset.x -= offset.x; this._anchorDragOffset.y -= offset.y; newAttrs.height += this.padding() * 2; } else if (this._movingAnchorName && newAttrs.height < 0 && this._movingAnchorName.indexOf('bottom') >= 0) { const offset = t.point({ x: 0, y: this.padding() * 2, }); this._movingAnchorName = this._movingAnchorName.replace('bottom', 'top'); this._anchorDragOffset.x -= offset.x; this._anchorDragOffset.y -= offset.y; newAttrs.height += this.padding() * 2; } if (this.boundBoxFunc()) { const bounded = this.boundBoxFunc()(oldAttrs, newAttrs); if (bounded) { newAttrs = bounded; } else { Util_1.Util.warn('boundBoxFunc returned falsy. You should return new bound rect from it!'); } } const baseSize = 10000000; const oldTr = new Util_1.Transform(); oldTr.translate(oldAttrs.x, oldAttrs.y); oldTr.rotate(oldAttrs.rotation); oldTr.scale(oldAttrs.width / baseSize, oldAttrs.height / baseSize); const newTr = new Util_1.Transform(); const newScaleX = newAttrs.width / baseSize; const newScaleY = newAttrs.height / baseSize; if (this.flipEnabled() === false) { newTr.translate(newAttrs.x, newAttrs.y); newTr.rotate(newAttrs.rotation); newTr.translate(newAttrs.width < 0 ? newAttrs.width : 0, newAttrs.height < 0 ? newAttrs.height : 0); newTr.scale(Math.abs(newScaleX), Math.abs(newScaleY)); } else { newTr.translate(newAttrs.x, newAttrs.y); newTr.rotate(newAttrs.rotation); newTr.scale(newScaleX, newScaleY); } const delta = newTr.multiply(oldTr.invert()); this._nodes.forEach((node) => { var _a; const parentTransform = node.getParent().getAbsoluteTransform(); const localTransform = node.getTransform().copy(); localTransform.translate(node.offsetX(), node.offsetY()); const newLocalTransform = new Util_1.Transform(); newLocalTransform .multiply(parentTransform.copy().invert()) .multiply(delta) .multiply(parentTransform) .multiply(localTransform); const attrs = newLocalTransform.decompose(); node.setAttrs(attrs); (_a = node.getLayer()) === null || _a === void 0 ? void 0 : _a.batchDraw(); }); this.rotation(Util_1.Util._getRotation(newAttrs.rotation)); this._nodes.forEach((node) => { this._fire('transform', { evt: evt, target: node }); node._fire('transform', { evt: evt, target: node }); }); this._resetTransformCache(); this.update(); this.getLayer().batchDraw(); } forceUpdate() { this._resetTransformCache(); this.update(); } _batchChangeChild(selector, attrs) { const anchor = this.findOne(selector); anchor.setAttrs(attrs); } update() { var _a; var attrs = this._getNodeRect(); this.rotation(Util_1.Util._getRotation(attrs.rotation)); var width = attrs.width; var height = attrs.height; var enabledAnchors = this.enabledAnchors(); var resizeEnabled = this.resizeEnabled(); var padding = this.padding(); var anchorSize = this.anchorSize(); const anchors = this.find('._anchor'); anchors.forEach((node) => { node.setAttrs({ width: anchorSize, height: anchorSize, offsetX: anchorSize / 2, offsetY: anchorSize / 2, stroke: this.anchorStroke(), strokeWidth: this.anchorStrokeWidth(), fill: this.anchorFill(), cornerRadius: this.anchorCornerRadius(), }); }); this._batchChangeChild('.top-left', { x: 0, y: 0, offsetX: anchorSize / 2 + padding, offsetY: anchorSize / 2 + padding, visible: resizeEnabled && enabledAnchors.indexOf('top-left') >= 0, }); this._batchChangeChild('.top-center', { x: width / 2, y: 0, offsetY: anchorSize / 2 + padding, visible: resizeEnabled && enabledAnchors.indexOf('top-center') >= 0, }); this._batchChangeChild('.top-right', { x: width, y: 0, offsetX: anchorSize / 2 - padding, offsetY: anchorSize / 2 + padding, visible: resizeEnabled && enabledAnchors.indexOf('top-right') >= 0, }); this._batchChangeChild('.middle-left', { x: 0, y: height / 2, offsetX: anchorSize / 2 + padding, visible: resizeEnabled && enabledAnchors.indexOf('middle-left') >= 0, }); this._batchChangeChild('.middle-right', { x: width, y: height / 2, offsetX: anchorSize / 2 - padding, visible: resizeEnabled && enabledAnchors.indexOf('middle-right') >= 0, }); this._batchChangeChild('.bottom-left', { x: 0, y: height, offsetX: anchorSize / 2 + padding, offsetY: anchorSize / 2 - padding, visible: resizeEnabled && enabledAnchors.indexOf('bottom-left') >= 0, }); this._batchChangeChild('.bottom-center', { x: width / 2, y: height, offsetY: anchorSize / 2 - padding, visible: resizeEnabled && enabledAnchors.indexOf('bottom-center') >= 0, }); this._batchChangeChild('.bottom-right', { x: width, y: height, offsetX: anchorSize / 2 - padding, offsetY: anchorSize / 2 - padding, visible: resizeEnabled && enabledAnchors.indexOf('bottom-right') >= 0, }); this._batchChangeChild('.rotater', { x: width / 2, y: -this.rotateAnchorOffset() * Util_1.Util._sign(height) - padding, visible: this.rotateEnabled(), }); this._batchChangeChild('.back', { width: width, height: height, visible: this.borderEnabled(), stroke: this.borderStroke(), strokeWidth: this.borderStrokeWidth(), dash: this.borderDash(), x: 0, y: 0, }); const styleFunc = this.anchorStyleFunc(); if (styleFunc) { anchors.forEach((node) => { styleFunc(node); }); } (_a = this.getLayer()) === null || _a === void 0 ? void 0 : _a.batchDraw(); } isTransforming() { return this._transforming; } stopTransform() { if (this._transforming) { this._removeEvents(); var anchorNode = this.findOne('.' + this._movingAnchorName); if (anchorNode) { anchorNode.stopDrag(); } } } destroy() { if (this.getStage() && this._cursorChange) { this.getStage().content && (this.getStage().content.style.cursor = ''); } Group_1.Group.prototype.destroy.call(this); this.detach(); this._removeEvents(); return this; } toObject() { return Node_1.Node.prototype.toObject.call(this); } clone(obj) { var node = Node_1.Node.prototype.clone.call(this, obj); return node; } getClientRect() { if (this.nodes().length > 0) { return super.getClientRect(); } else { return { x: 0, y: 0, width: 0, height: 0 }; } } } exports.Transformer = Transformer; Transformer.isTransforming = () => { return activeTransformersCount > 0; }; function validateAnchors(val) { if (!(val instanceof Array)) { Util_1.Util.warn('enabledAnchors value should be an array'); } if (val instanceof Array) { val.forEach(function (name) { if (ANCHORS_NAMES.indexOf(name) === -1) { Util_1.Util.warn('Unknown anchor name: ' + name + '. Available names are: ' + ANCHORS_NAMES.join(', ')); } }); } return val || []; } Transformer.prototype.className = 'Transformer'; (0, Global_2._registerNode)(Transformer); Factory_1.Factory.addGetterSetter(Transformer, 'enabledAnchors', ANCHORS_NAMES, validateAnchors); Factory_1.Factory.addGetterSetter(Transformer, 'flipEnabled', true, (0, Validators_1.getBooleanValidator)()); Factory_1.Factory.addGetterSetter(Transformer, 'resizeEnabled', true); Factory_1.Factory.addGetterSetter(Transformer, 'anchorSize', 10, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Transformer, 'rotateEnabled', true); Factory_1.Factory.addGetterSetter(Transformer, 'rotateLineVisible', true); Factory_1.Factory.addGetterSetter(Transformer, 'rotationSnaps', []); Factory_1.Factory.addGetterSetter(Transformer, 'rotateAnchorOffset', 50, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Transformer, 'rotateAnchorCursor', 'crosshair'); Factory_1.Factory.addGetterSetter(Transformer, 'rotationSnapTolerance', 5, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Transformer, 'borderEnabled', true); Factory_1.Factory.addGetterSetter(Transformer, 'anchorStroke', 'rgb(0, 161, 255)'); Factory_1.Factory.addGetterSetter(Transformer, 'anchorStrokeWidth', 1, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Transformer, 'anchorFill', 'white'); Factory_1.Factory.addGetterSetter(Transformer, 'anchorCornerRadius', 0, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Transformer, 'borderStroke', 'rgb(0, 161, 255)'); Factory_1.Factory.addGetterSetter(Transformer, 'borderStrokeWidth', 1, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Transformer, 'borderDash'); Factory_1.Factory.addGetterSetter(Transformer, 'keepRatio', true); Factory_1.Factory.addGetterSetter(Transformer, 'shiftBehavior', 'default'); Factory_1.Factory.addGetterSetter(Transformer, 'centeredScaling', false); Factory_1.Factory.addGetterSetter(Transformer, 'ignoreStroke', false); Factory_1.Factory.addGetterSetter(Transformer, 'padding', 0, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Transformer, 'node'); Factory_1.Factory.addGetterSetter(Transformer, 'nodes'); Factory_1.Factory.addGetterSetter(Transformer, 'boundBoxFunc'); Factory_1.Factory.addGetterSetter(Transformer, 'anchorDragBoundFunc'); Factory_1.Factory.addGetterSetter(Transformer, 'anchorStyleFunc'); Factory_1.Factory.addGetterSetter(Transformer, 'shouldOverdrawWholeArea', false); Factory_1.Factory.addGetterSetter(Transformer, 'useSingleNodeRotation', true); Factory_1.Factory.backCompat(Transformer, { lineEnabled: 'borderEnabled', rotateHandlerOffset: 'rotateAnchorOffset', enabledHandlers: 'enabledAnchors', });