UNPKG

@logicflow/extension

Version:
236 lines (235 loc) 8.77 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 }); exports.getCurvedEdgePath = exports.CurvedEdgeModel = exports.CurvedEdge = void 0; var core_1 = require("@logicflow/core"); // 方向组合到圆弧象限的映射。 // key 由进入方向(dir1)和离开方向(dir2)拼接,例如 'tr' 表示从上(t)到右(r)的拐角。 // 通过该映射确定在拐点处应该绘制的圆弧象限,用于计算中间控制点。 var directionMap = { tr: 'tl', lb: 'tl', tl: 'tr', rb: 'tr', br: 'bl', lt: 'bl', bl: 'br', rt: 'br', }; // 过滤折线中的共线中间点,减少不必要的顶点 function pointFilter(points) { // 原地修改传入的数组 var all = points; // 从第二个点开始,检查三点是否共线 var i = 1; while (i < all.length - 1) { var _a = __read(all[i - 1], 2), x = _a[0], y = _a[1]; var _b = __read(all[i], 2), x1 = _b[0], y1 = _b[1]; var _c = __read(all[i + 1], 2), x2 = _c[0], y2 = _c[1]; // 如果三点在同一条水平或垂直直线上,删除中间点 if ((x === x1 && x1 === x2) || (y === y1 && y1 === y2)) { all.splice(i, 1); } else { i++; } } // 返回精简后的点集 return all; } function getMidPoints(cur, key, orientation, radius) { var mid1 = [cur[0], cur[1]]; var mid2 = [cur[0], cur[1]]; switch (orientation) { case 'tl': { if (key === 'tr') { mid1[1] += radius; mid2[0] += radius; } else if (key === 'lb') { mid1[0] += radius; mid2[1] += radius; } return [mid1, mid2]; } case 'tr': { if (key === 'tl') { mid1[1] += radius; mid2[0] -= radius; } else if (key === 'rb') { mid1[0] -= radius; mid2[1] += radius; } return [mid1, mid2]; } case 'bl': { if (key === 'br') { mid1[1] -= radius; mid2[0] += radius; } else if (key === 'lt') { mid1[0] += radius; mid2[1] -= radius; } return [mid1, mid2]; } case 'br': { if (key === 'bl') { mid1[1] -= radius; mid2[0] -= radius; } else if (key === 'rt') { mid1[0] -= radius; mid2[1] -= radius; } return [mid1, mid2]; } default: return []; } } /** * 生成局部路径片段(包含圆角) * - 输入为上一个顶点、当前拐点、下一个顶点,计算方向组合并选择圆弧象限 * - 将圆角半径限制在相邻两段长度的一半以内,避免过度弯曲 * @param prevPoint 上一个顶点 * @param cornerPoint 当前拐点(圆角所在拐点) * @param nextPoint 下一个顶点 * @param cornerRadius 圆角半径上限 * @returns 局部 path 字符串(包含 L/Q 操作) */ function getPartialPath(prevPoint, cornerPoint, nextPoint, cornerRadius) { var _a; // 轴对齐容差(像素),用于消除微小误差 var epsilon = 1; var resolveDir = function (a, b) { var dx = b[0] - a[0]; var dy = b[1] - a[1]; var adx = Math.abs(dx); var ady = Math.abs(dy); if (ady <= epsilon && adx > epsilon) { return dx < 0 ? 'l' : 'r'; } if (adx <= epsilon && ady > epsilon) { return dy < 0 ? 't' : 'b'; } if (adx <= epsilon && ady <= epsilon) { return ''; } // 非严格对齐时,选择更接近的轴 return adx < ady ? (dx < 0 ? 'l' : 'r') : dy < 0 ? 't' : 'b'; }; var dir1 = resolveDir(prevPoint, cornerPoint); var dir2 = resolveDir(cornerPoint, nextPoint); var r = Math.min(Math.hypot(cornerPoint[0] - prevPoint[0], cornerPoint[1] - prevPoint[1]) / 2, Math.hypot(nextPoint[0] - cornerPoint[0], nextPoint[1] - cornerPoint[1]) / 2, cornerRadius) || (1 / 5) * cornerRadius; var key = "".concat(dir1).concat(dir2); var orientation = directionMap[key] || '-'; var path = ''; if (orientation === '-') { // 仅移动到当前拐点,由下一次迭代决定如何从拐点继续(直线或圆角) path += "L ".concat(cornerPoint[0], " ").concat(cornerPoint[1]); } else { var _b = __read(getMidPoints(cornerPoint, key, orientation, r), 2), mid1 = _b[0], mid2 = _b[1]; if (mid1 && mid2) { path += "L ".concat(mid1[0], " ").concat(mid1[1], " Q ").concat(cornerPoint[0], " ").concat(cornerPoint[1], " ").concat(mid2[0], " ").concat(mid2[1]); _a = __read(mid2, 2), cornerPoint[0] = _a[0], cornerPoint[1] = _a[1]; } } return path; } function getCurvedEdgePath(points, radius) { var i = 0; var d = ''; if (points.length === 2) { d += "M".concat(points[i][0], " ").concat(points[i++][1], " L ").concat(points[i][0], " ").concat(points[i][1]); } else { d += "M".concat(points[i][0], " ").concat(points[i++][1]); for (; i + 1 < points.length;) { var prev = points[i - 1]; var cur = points[i]; var next = points[i++ + 1]; d += getPartialPath(prev, cur, next, radius); } d += "L ".concat(points[i][0], " ").concat(points[i][1]); } return d; } exports.getCurvedEdgePath = getCurvedEdgePath; var CurvedEdge = /** @class */ (function (_super) { __extends(CurvedEdge, _super); function CurvedEdge() { return _super !== null && _super.apply(this, arguments) || this; } CurvedEdge.prototype.getEdge = function () { var model = this.props.model; var pointsStr = model.points, isAnimation = model.isAnimation, arrowConfig = model.arrowConfig, _a = model.radius, radius = _a === void 0 ? 5 : _a; var style = model.getEdgeStyle(); var animationStyle = model.getEdgeAnimationStyle(); var points = pointFilter(pointsStr.split(' ').map(function (p) { return p.split(',').map(function (a) { return +a; }); })); var d = getCurvedEdgePath(points, radius); var attrs = __assign(__assign(__assign({ style: isAnimation ? animationStyle : {} }, style), arrowConfig), { fill: 'none' }); return (0, core_1.h)('path', __assign({ d: d }, attrs)); }; return CurvedEdge; }(core_1.PolylineEdge)); exports.CurvedEdge = CurvedEdge; var CurvedEdgeModel = /** @class */ (function (_super) { __extends(CurvedEdgeModel, _super); function CurvedEdgeModel() { return _super !== null && _super.apply(this, arguments) || this; } return CurvedEdgeModel; }(core_1.PolylineEdgeModel)); exports.CurvedEdgeModel = CurvedEdgeModel; var defaultCurvedEdge = { type: 'curved-edge', view: CurvedEdge, model: CurvedEdgeModel, }; exports.default = defaultCurvedEdge;