UNPKG

@logicflow/extension

Version:
487 lines (486 loc) 21.2 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; Object.defineProperty(exports, "__esModule", { value: true }); var jsx_runtime_1 = require("preact/jsx-runtime"); var core_1 = require("@logicflow/core"); var StepDrag = core_1.LogicFlowUtil.StepDrag; var Control = /** @class */ (function (_super) { __extends(Control, _super); function Control(props) { var _this = _super.call(this) || this; // 更新中心点位置,更新文案位置 _this.updatePosition = function (_a) { var deltaX = _a.deltaX, deltaY = _a.deltaY; var _b = _this.nodeModel, x = _b.x, y = _b.y; _this.nodeModel.x = x + deltaX / 2; _this.nodeModel.y = y + deltaY / 2; _this.nodeModel.moveText(deltaX / 2, deltaY / 2); }; // 计算control拖动后,节点的宽高 _this.getResize = function (_a) { var index = _a.index, deltaX = _a.deltaX, deltaY = _a.deltaY, width = _a.width, height = _a.height, PCTResizeInfo = _a.PCTResizeInfo, _b = _a.pct, pct = _b === void 0 ? 1 : _b, _c = _a.freezeWidth, freezeWidth = _c === void 0 ? false : _c, _d = _a.freezeHeight, freezeHeight = _d === void 0 ? false : _d; // TODO: 定义 getResize 方法的参数类型 var resize = { width: width, height: height, deltaX: deltaX, deltaY: deltaY, }; if (PCTResizeInfo) { var sensitivity = 4; // 越低越灵敏 var deltaScale = 0; var combineDelta = 0; switch (index) { case 0: combineDelta = (deltaX * -1 - deltaY) / sensitivity; break; case 1: combineDelta = (deltaX - deltaY) / sensitivity; break; case 2: combineDelta = (deltaX + deltaY) / sensitivity; break; case 3: combineDelta = (deltaX * -1 + deltaY) / sensitivity; break; default: break; } if (combineDelta !== 0) { deltaScale = Math.round((combineDelta / PCTResizeInfo.ResizeBasis.basisHeight) * 100000) / 1000; } PCTResizeInfo.ResizePCT.widthPCT = Math.max(Math.min(PCTResizeInfo.ResizePCT.widthPCT + deltaScale, PCTResizeInfo.ScaleLimit.maxScaleLimit), PCTResizeInfo.ScaleLimit.minScaleLimit); PCTResizeInfo.ResizePCT.heightPCT = Math.max(Math.min(PCTResizeInfo.ResizePCT.heightPCT + deltaScale, PCTResizeInfo.ScaleLimit.maxScaleLimit), PCTResizeInfo.ScaleLimit.minScaleLimit); var spcWidth = Math.round((PCTResizeInfo.ResizePCT.widthPCT * PCTResizeInfo.ResizeBasis.basisWidth) / 100); var spcHeight = Math.round((PCTResizeInfo.ResizePCT.heightPCT * PCTResizeInfo.ResizeBasis.basisHeight) / 100); switch (index) { case 0: deltaX = width - spcWidth; deltaY = height - spcHeight; break; case 1: deltaX = spcWidth - width; deltaY = height - spcHeight; break; case 2: deltaX = spcWidth - width; deltaY = spcHeight - height; break; case 3: deltaX = width - spcWidth; deltaY = spcHeight - height; break; default: break; } resize.width = spcWidth; resize.height = spcHeight; resize.deltaX = deltaX / pct; resize.deltaY = deltaY / pct; return resize; } // 如果限制了宽/高不变,对应的width/height保持一致 switch (index) { case 0: resize.width = freezeWidth ? width : width - deltaX * pct; resize.height = freezeHeight ? height : height - deltaY * pct; break; case 1: resize.width = freezeWidth ? width : width + deltaX * pct; resize.height = freezeHeight ? height : height - deltaY * pct; break; case 2: resize.width = freezeWidth ? width : width + deltaX * pct; resize.height = freezeHeight ? height : height + deltaY * pct; break; case 3: resize.width = freezeWidth ? width : width - deltaX * pct; resize.height = freezeHeight ? height : height + deltaY * pct; break; default: break; } return resize; }; _this.updateEdgePointByAnchors = function () { // https://github.com/didi/LogicFlow/issues/807 // https://github.com/didi/LogicFlow/issues/875 // 之前的做法,比如Rect是使用getRectResizeEdgePoint()计算边的point缩放后的位置 // getRectResizeEdgePoint()考虑了瞄点在四条边以及在4个圆角的情况 // 使用的是一种等比例缩放的模式,比如: // const pct = (y - beforeNode.y) / (beforeNode.height / 2 - radius) // afterPoint.y = afterNode.y + (afterNode.height / 2 - radius) * pct // 但是用户自定义的getDefaultAnchor()不一定是按照比例编写的 // 它可能是 x: x + 20:每次缩放都会保持在x右边20的位置,因此用户自定义瞄点时,然后产生无法跟随的问题 // 现在的做法是:直接获取用户自定义瞄点的位置,然后用这个位置作为边的新的起点,而不是自己进行计算 var _a = _this.nodeModel, id = _a.id, anchors = _a.anchors; var edges = _this.getNodeEdges(id); // 更新边 edges.sourceEdges.forEach(function (item) { var anchorItem = anchors.find(function (anchor) { return anchor.id === item.sourceAnchorId; }); if (anchorItem) { item.updateStartPoint({ x: anchorItem.x, y: anchorItem.y, }); } }); edges.targetEdges.forEach(function (item) { var anchorItem = anchors.find(function (anchor) { return anchor.id === item.targetAnchorId; }); if (anchorItem) { item.updateEndPoint({ x: anchorItem.x, y: anchorItem.y, }); } }); }; // 矩形更新 _this.updateRect = function (_a) { var deltaX = _a.deltaX, deltaY = _a.deltaY; var _b = _this .nodeModel, x = _b.x, y = _b.y, width = _b.width, height = _b.height, radius = _b.radius, PCTResizeInfo = _b.PCTResizeInfo; var _c = _this .nodeModel, minWidth = _c.minWidth, minHeight = _c.minHeight, maxWidth = _c.maxWidth, maxHeight = _c.maxHeight; // 更新中心点位置,更新文案位置 var index = _this.index; var freezeWidth = minWidth === maxWidth; var freezeHeight = minHeight === maxHeight; var size = _this.getResize({ index: index, deltaX: deltaX, deltaY: deltaY, width: width, height: height, PCTResizeInfo: PCTResizeInfo, pct: 1, freezeWidth: freezeWidth, freezeHeight: freezeHeight, }); // 限制放大缩小的最大最小范围 if (size.width < minWidth || size.width > maxWidth || size.height < minHeight || size.height > maxHeight) { // 为了避免放到和缩小位置和鼠标不一致的问题 _this.dragHandler.cancelDrag(); return; } // 如果限制了宽/高不变,对应的x/y不产生位移 _this.updatePosition({ deltaX: freezeWidth ? 0 : size.deltaX, deltaY: freezeHeight ? 0 : size.deltaY, }); // 更新宽高 _this.nodeModel.width = size.width; _this.nodeModel.height = size.height; _this.nodeModel.setProperties({ nodeSize: { width: size.width, height: size.height, }, }); // const edges = this.getNodeEdges(id) var beforeNode = { x: x, y: y, width: width, height: height, radius: radius, }; var afterNode = { x: _this.nodeModel.x, y: _this.nodeModel.y, width: _this.nodeModel.width, height: _this.nodeModel.height, radius: radius, }; // 更新边 _this.updateEdgePointByAnchors(); _this.eventEmit({ deltaX: deltaX, deltaY: deltaY, beforeNode: beforeNode, afterNode: afterNode, }); }; // 椭圆更新 _this.updateEllipse = function (_a) { var deltaX = _a.deltaX, deltaY = _a.deltaY; var _b = _this.nodeModel, rx = _b.rx, ry = _b.ry, x = _b.x, y = _b.y, PCTResizeInfo = _b.PCTResizeInfo; var index = _this.index; var _c = _this .nodeModel, minWidth = _c.minWidth, minHeight = _c.minHeight, maxWidth = _c.maxWidth, maxHeight = _c.maxHeight; var freezeWidth = minWidth === maxWidth; var freezeHeight = minHeight === maxHeight; var width = rx; var height = ry; var size = _this.getResize({ index: index, deltaX: deltaX, deltaY: deltaY, width: width, height: height, PCTResizeInfo: PCTResizeInfo, pct: 1 / 2, freezeWidth: freezeWidth, freezeHeight: freezeHeight, }); // 限制放大缩小的最大最小范围 if (size.width < minWidth / 2 || size.width > maxWidth / 2 || size.height < minHeight / 2 || size.height > maxHeight / 2) { _this.dragHandler.cancelDrag(); return; } // 更新中心点位置,更新文案位置 // 如果限制了宽/高不变,对应的x/y不产生位移 _this.updatePosition({ deltaX: freezeWidth ? 0 : size.deltaX, deltaY: freezeHeight ? 0 : size.deltaY, }); // 更新rx ry,宽高为计算属性自动更新 // @ts-ignore _this.nodeModel.rx = size.width; // @ts-ignore _this.nodeModel.ry = size.height; _this.nodeModel.setProperties({ nodeSize: { rx: size.width, ry: size.height, }, }); var beforeNode = { x: x, y: y, }; var afterNode = { rx: size.width, ry: size.height, x: _this.nodeModel.x, y: _this.nodeModel.y, }; // 更新边 _this.updateEdgePointByAnchors(); _this.eventEmit({ deltaX: deltaX, deltaY: deltaY, beforeNode: __assign(__assign({}, beforeNode), { rx: rx, ry: ry }), afterNode: afterNode, }); }; // 菱形更新 _this.updateDiamond = function (_a) { var deltaX = _a.deltaX, deltaY = _a.deltaY; var _b = _this.nodeModel, rx = _b.rx, ry = _b.ry, x = _b.x, y = _b.y, PCTResizeInfo = _b.PCTResizeInfo; var index = _this.index; var _c = _this .nodeModel, minWidth = _c.minWidth, minHeight = _c.minHeight, maxWidth = _c.maxWidth, maxHeight = _c.maxHeight; var freezeWidth = minWidth === maxWidth; var freezeHeight = minHeight === maxHeight; var width = rx; var height = ry; var size = _this.getResize({ index: index, deltaX: deltaX, deltaY: deltaY, width: width, height: height, PCTResizeInfo: PCTResizeInfo, pct: 1 / 2, freezeWidth: freezeWidth, freezeHeight: freezeHeight, }); // 限制放大缩小的最大最小范围 if (size.width < minWidth / 2 || size.width > maxWidth / 2 || size.height < minHeight / 2 || size.height > maxHeight / 2) { _this.dragHandler.cancelDrag(); return; } // 更新中心点位置,更新文案位置 // 如果限制了宽/高不变,对应的x/y不产生位移 _this.updatePosition({ deltaX: freezeWidth ? 0 : size.deltaX, deltaY: freezeHeight ? 0 : size.deltaY, }); // 更新rx ry,宽高为计算属性自动更新 // @ts-ignore _this.nodeModel.rx = size.width; // @ts-ignore _this.nodeModel.ry = size.height; _this.nodeModel.setProperties({ nodeSize: { rx: size.width, ry: size.height, }, }); var beforeNode = { x: x, y: y, rx: rx, ry: ry, }; var afterNode = { rx: size.width, ry: size.height, x: _this.nodeModel.x, y: _this.nodeModel.y, }; // 更新边 _this.updateEdgePointByAnchors(); _this.eventEmit({ deltaX: deltaX, deltaY: deltaY, beforeNode: beforeNode, afterNode: afterNode, }); }; _this.eventEmit = function (_a) { var deltaX = _a.deltaX, deltaY = _a.deltaY, beforeNode = _a.beforeNode, afterNode = _a.afterNode; var _b = _this.nodeModel, id = _b.id, modelType = _b.modelType, type = _b.type; var oldNodeSize = __assign({ id: id, modelType: modelType, type: type }, beforeNode); var newNodeSize = __assign({ id: id, modelType: modelType, type: type }, afterNode); _this.graphModel.eventCenter.emit('node:resize', { preData: oldNodeSize, data: newNodeSize, deltaX: deltaX, deltaY: deltaY, index: _this.index, model: _this.nodeModel, }); }; _this.onDragging = function (_a) { var _b; var deltaX = _a.deltaX, deltaY = _a.deltaY; var transformModel = _this.graphModel.transformModel; var modelType = _this.nodeModel.modelType; _b = __read(transformModel.fixDeltaXY(deltaX, deltaY), 2), deltaX = _b[0], deltaY = _b[1]; // html和矩形的计算方式是一样的,共用一个方法 if (modelType === core_1.ModelType.RECT_NODE || modelType === core_1.ModelType.HTML_NODE) { _this.updateRect({ deltaX: deltaX, deltaY: deltaY, }); // this.nodeModel.resize(deltaX, deltaY); } else if (modelType === core_1.ModelType.ELLIPSE_NODE) { _this.updateEllipse({ deltaX: deltaX, deltaY: deltaY, }); } else if (modelType === core_1.ModelType.DIAMOND_NODE) { _this.updateDiamond({ deltaX: deltaX, deltaY: deltaY, }); } }; /** * 由于将拖拽放大缩小改成丝滑模式,这个时候需要在拖拽结束的时候,将节点的位置更新到grid上. */ _this.onDragEnd = function () { var _a = _this.graphModel.gridSize, gridSize = _a === void 0 ? 1 : _a; var x = gridSize * Math.round(_this.nodeModel.x / gridSize); var y = gridSize * Math.round(_this.nodeModel.y / gridSize); _this.nodeModel.moveTo(x, y); // 先触发onDragging()->更新边->再触发用户自定义的getDefaultAnchor(),所以onDragging()拿到的anchors是滞后的 // 为了正确设置最终的位置,应该在拖拽结束的时候,再设置一次边的Point位置,此时拿到的anchors是最新的 _this.updateEdgePointByAnchors(); }; _this.index = props.index; _this.nodeModel = props.model; _this.graphModel = props.graphModel; // 为保证对齐线功能正常使用,step默认是网格grid的两倍, // 没有网格设置,默认为2,保证坐标是整数 // let step = 2; // if (gridSize > 1) { // step = 2 * gridSize; // } // if (this.nodeModel.gridSize) { // step = 2 * this.nodeModel.gridSize; // } _this.dragHandler = new StepDrag({ onDragging: _this.onDragging, onDragEnd: _this.onDragEnd, step: 1, }); return _this; } Control.prototype.getNodeEdges = function (nodeId) { var graphModel = this.graphModel; var edges = graphModel.edges; var sourceEdges = []; var targetEdges = []; for (var i = 0; i < edges.length; i++) { var edgeModel = edges[i]; if (edgeModel.sourceNodeId === nodeId) { sourceEdges.push(edgeModel); } else if (edges[i].targetNodeId === nodeId) { targetEdges.push(edgeModel); } } return { sourceEdges: sourceEdges, targetEdges: targetEdges, }; }; Control.prototype.render = function () { var _a = this.props, x = _a.x, y = _a.y, index = _a.index, model = _a.model; var style = model.getControlPointStyle(); return ((0, jsx_runtime_1.jsx)("g", { className: "lf-resize-control-".concat(index), children: (0, jsx_runtime_1.jsx)(core_1.Rect, __assign({ className: "lf-node-control", x: x, y: y }, style, { onMouseDown: this.dragHandler.handleMouseDown })) })); }; return Control; }(core_1.Component)); exports.default = Control;