@logicflow/core 2.0.10 → 2.0.12

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 (59) hide show
  1. package/.turbo/turbo-build$colon$dev.log +2 -2
  2. package/.turbo/turbo-build.log +6 -6
  3. package/CHANGELOG.md +24 -5
  4. package/dist/index.min.js +1 -1
  5. package/dist/index.min.js.map +1 -1
  6. package/es/LogicFlow.js +7 -0
  7. package/es/constant/index.d.ts +2 -0
  8. package/es/constant/index.js +2 -0
  9. package/es/event/eventArgs.d.ts +8 -0
  10. package/es/model/GraphModel.js +3 -0
  11. package/es/model/edge/BezierEdgeModel.js +5 -2
  12. package/es/model/edge/PolylineEdgeModel.js +5 -2
  13. package/es/model/node/BaseNodeModel.js +4 -0
  14. package/es/tool/index.js +2 -2
  15. package/es/util/node.d.ts +1 -1
  16. package/es/util/node.js +32 -16
  17. package/es/view/Anchor.js +15 -2
  18. package/es/view/Control.d.ts +1 -0
  19. package/es/view/Control.js +4 -0
  20. package/es/view/Graph.d.ts +3 -0
  21. package/es/view/Graph.js +7 -3
  22. package/es/view/node/BaseNode.js +1 -5
  23. package/es/view/overlay/ToolOverlay.d.ts +3 -1
  24. package/es/view/overlay/ToolOverlay.js +39 -2
  25. package/lib/LogicFlow.js +7 -0
  26. package/lib/constant/index.d.ts +2 -0
  27. package/lib/constant/index.js +2 -0
  28. package/lib/event/eventArgs.d.ts +8 -0
  29. package/lib/model/GraphModel.js +3 -0
  30. package/lib/model/edge/BezierEdgeModel.js +4 -1
  31. package/lib/model/edge/PolylineEdgeModel.js +4 -1
  32. package/lib/model/node/BaseNodeModel.js +4 -0
  33. package/lib/tool/index.js +2 -2
  34. package/lib/util/node.d.ts +1 -1
  35. package/lib/util/node.js +32 -16
  36. package/lib/view/Anchor.js +15 -2
  37. package/lib/view/Control.d.ts +1 -0
  38. package/lib/view/Control.js +4 -0
  39. package/lib/view/Graph.d.ts +3 -0
  40. package/lib/view/Graph.js +6 -2
  41. package/lib/view/node/BaseNode.js +0 -4
  42. package/lib/view/overlay/ToolOverlay.d.ts +3 -1
  43. package/lib/view/overlay/ToolOverlay.js +39 -2
  44. package/package.json +1 -1
  45. package/src/LogicFlow.tsx +6 -0
  46. package/src/constant/index.ts +2 -0
  47. package/src/event/eventArgs.ts +8 -0
  48. package/src/model/GraphModel.ts +1 -1
  49. package/src/model/edge/BezierEdgeModel.ts +3 -3
  50. package/src/model/edge/PolylineEdgeModel.ts +3 -3
  51. package/src/model/node/BaseNodeModel.ts +4 -0
  52. package/src/tool/index.ts +2 -2
  53. package/src/util/node.ts +19 -18
  54. package/src/view/Anchor.tsx +15 -4
  55. package/src/view/Control.tsx +5 -0
  56. package/src/view/Graph.tsx +15 -3
  57. package/src/view/node/BaseNode.tsx +0 -6
  58. package/src/view/overlay/ToolOverlay.tsx +17 -2
  59. package/stats.html +1 -1
package/lib/util/node.js CHANGED
@@ -10,12 +10,29 @@ var __assign = (this && this.__assign) || function () {
10
10
  };
11
11
  return __assign.apply(this, arguments);
12
12
  };
13
+ var __read = (this && this.__read) || function (o, n) {
14
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
15
+ if (!m) return o;
16
+ var i = m.call(o), r, ar = [], e;
17
+ try {
18
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
19
+ }
20
+ catch (error) { e = { error: error }; }
21
+ finally {
22
+ try {
23
+ if (r && !r.done && (m = i["return"])) m.call(i);
24
+ }
25
+ finally { if (e) throw e.error; }
26
+ }
27
+ return ar;
28
+ };
13
29
  Object.defineProperty(exports, "__esModule", { value: true });
14
30
  exports.formatAnchorConnectValidateData = exports.getSvgTextWidthHeight = exports.getHtmlTextHeight = exports.getNodeAnchorPosition = exports.pickNodeConfig = exports.getCrossPointWithPolygon = exports.getCrossPointWithEllipse = exports.inStraightLineOfRect = exports.pointEdgeDirection = exports.getCrossPointWithCircle = exports.getClosestRadiusCenter = exports.getRectRadiusCircle = exports.getNodeBBox = exports.isInNodeBbox = exports.isInNode = exports.distance = exports.getClosestAnchor = exports.targetNodeInfo = exports.getAnchors = void 0;
15
31
  var lodash_es_1 = require("lodash-es");
16
32
  var edge_1 = require("./edge");
17
33
  var constant_1 = require("../constant");
18
34
  var edge_2 = require("../algorithm/edge");
35
+ var matrix_1 = require("./matrix");
19
36
  /* 获取所有锚点 */
20
37
  var getAnchors = function (data) {
21
38
  var anchors = data.anchors;
@@ -79,30 +96,29 @@ exports.getClosestAnchor = getClosestAnchor;
79
96
  var distance = function (x1, y1, x2, y2) { return Math.hypot(x1 - x2, y1 - y2); };
80
97
  exports.distance = distance;
81
98
  /* 是否在某个节点内,手否进行连接,有offset控制粒度,与outline有关,可以优化 */
82
- var isInNode = function (position, node) {
99
+ var isInNode = function (position, node, offset) {
100
+ if (offset === void 0) { offset = 0; }
83
101
  var inNode = false;
84
- var offset = 0;
85
102
  var bBox = (0, exports.getNodeBBox)(node);
86
- if (position.x >= bBox.minX - offset &&
87
- position.x <= bBox.maxX + offset &&
88
- position.y >= bBox.minY - offset &&
89
- position.y <= bBox.maxY + offset) {
103
+ var _a = __read(new matrix_1.Matrix([position.x, position.y, 1])
104
+ .translate(-node.x, -node.y)
105
+ .rotate(-node.rotate)
106
+ .translate(node.x, node.y)[0], 2), x = _a[0], y = _a[1];
107
+ var reverseRotatedPosition = {
108
+ x: x,
109
+ y: y,
110
+ };
111
+ if (reverseRotatedPosition.x >= bBox.minX - offset &&
112
+ reverseRotatedPosition.x <= bBox.maxX + offset &&
113
+ reverseRotatedPosition.y >= bBox.minY - offset &&
114
+ reverseRotatedPosition.y <= bBox.maxY + offset) {
90
115
  inNode = true;
91
116
  }
92
117
  return inNode;
93
118
  };
94
119
  exports.isInNode = isInNode;
95
120
  var isInNodeBbox = function (position, node) {
96
- var inNode = false;
97
- var offset = 5;
98
- var bBox = (0, exports.getNodeBBox)(node);
99
- if (position.x >= bBox.minX - offset &&
100
- position.x <= bBox.maxX + offset &&
101
- position.y >= bBox.minY - offset &&
102
- position.y <= bBox.maxY + offset) {
103
- inNode = true;
104
- }
105
- return inNode;
121
+ return (0, exports.isInNode)(position, node, 5);
106
122
  };
107
123
  exports.isInNodeBbox = isInNodeBbox;
108
124
  /* 获取节点bbox */
@@ -296,10 +296,23 @@ var Anchor = /** @class */ (function (_super) {
296
296
  Anchor.prototype.render = function () {
297
297
  var _this = this;
298
298
  var _a = this.state, startX = _a.startX, startY = _a.startY, endX = _a.endX, endY = _a.endY;
299
- var _b = this.props, edgeAddable = _b.anchorData.edgeAddable, edgeStyle = _b.edgeStyle;
299
+ var _b = this.props, anchorData = _b.anchorData, edgeStyle = _b.edgeStyle, nodeModel = _b.nodeModel, graphModel = _b.graphModel;
300
+ var edgeAddable = anchorData.edgeAddable;
300
301
  return (
301
302
  // className="lf-anchor" 作为下载时,需要将锚点删除的依据,不要修改类名
302
- (0, jsx_runtime_1.jsxs)("g", { className: "lf-anchor", children: [(0, jsx_runtime_1.jsx)("g", { onMouseDown: function (ev) {
303
+ (0, jsx_runtime_1.jsxs)("g", { className: "lf-anchor", children: [(0, jsx_runtime_1.jsx)("g", { onClick: function (ev) {
304
+ ev.stopPropagation();
305
+ graphModel.eventCenter.emit(constant_1.EventType.ANCHOR_CLICK, {
306
+ data: anchorData,
307
+ e: ev,
308
+ nodeModel: nodeModel,
309
+ });
310
+ }, onMouseDown: function (ev) {
311
+ graphModel.eventCenter.emit(constant_1.EventType.ANCHOR_MOUSEDOWN, {
312
+ data: anchorData,
313
+ e: ev,
314
+ nodeModel: nodeModel,
315
+ });
303
316
  if (edgeAddable !== false) {
304
317
  _this.dragHandler.handleMouseDown(ev);
305
318
  }
@@ -43,6 +43,7 @@ export declare class ResizeControl extends Component<IResizeControlProps, IResiz
43
43
  */
44
44
  recalcResizeInfo: (index: ResizeControlIndex, resizeInfo: ResizeInfo, pct?: number, freezeWidth?: boolean, freezeHeight?: boolean) => ResizeInfo;
45
45
  resizeNode: ({ deltaX, deltaY }: VectorData) => void;
46
+ onDragStart: () => void;
46
47
  onDragging: ({ deltaX, deltaY }: IDragParams) => void;
47
48
  onDragEnd: () => void;
48
49
  render(): h.JSX.Element;
@@ -283,6 +283,9 @@ var ResizeControl = /** @class */ (function (_super) {
283
283
  // // 触发 resize 事件
284
284
  // this.triggerResizeEvent(preNodeData, curNodeData, deltaX, deltaY, this.index, this.nodeModel)
285
285
  };
286
+ _this.onDragStart = function () {
287
+ _this.graphModel.selectNodeById(_this.nodeModel.id);
288
+ };
286
289
  _this.onDragging = function (_a) {
287
290
  var deltaX = _a.deltaX, deltaY = _a.deltaY;
288
291
  var transformModel = _this.graphModel.transformModel;
@@ -312,6 +315,7 @@ var ResizeControl = /** @class */ (function (_super) {
312
315
  _this.graphModel = graphModel;
313
316
  // 初始化拖拽工具
314
317
  _this.dragHandler = new util_1.StepDrag({
318
+ onDragStart: _this.onDragStart,
315
319
  onDragging: _this.onDragging,
316
320
  onDragEnd: _this.onDragEnd,
317
321
  step: graphModel.gridSize,
@@ -1,4 +1,5 @@
1
1
  import { Component, ComponentType } from 'preact/compat';
2
+ import { CanvasOverlay } from './overlay';
2
3
  import DnD from './behavior/dnd';
3
4
  import Tool from '../tool';
4
5
  import { Options as LFOptions } from '../options';
@@ -12,6 +13,8 @@ type IGraphProps = {
12
13
  graphModel: GraphModel;
13
14
  };
14
15
  declare class Graph extends Component<IGraphProps> {
16
+ canvasOverlayRef: import("preact").RefObject<CanvasOverlay>;
17
+ getCanvasOverlay: () => CanvasOverlay | null;
15
18
  private handleResize;
16
19
  private throttleResize;
17
20
  componentDidMount(): void;
package/lib/view/Graph.js CHANGED
@@ -56,6 +56,10 @@ var Graph = /** @class */ (function (_super) {
56
56
  __extends(Graph, _super);
57
57
  function Graph() {
58
58
  var _this = _super.apply(this, __spreadArray([], __read(arguments), false)) || this;
59
+ _this.canvasOverlayRef = (0, compat_1.createRef)();
60
+ _this.getCanvasOverlay = function () {
61
+ return _this.canvasOverlayRef.current;
62
+ };
59
63
  _this.handleResize = function () {
60
64
  var _a = _this.props, graphModel = _a.graphModel, options = _a.options;
61
65
  var width = graphModel.width, height = graphModel.height, isContainerWidth = graphModel.isContainerWidth, isContainerHeight = graphModel.isContainerHeight;
@@ -112,9 +116,9 @@ var Graph = /** @class */ (function (_super) {
112
116
  }
113
117
  var fakeNode = graphModel.fakeNode, editConfigModel = graphModel.editConfigModel, background = graphModel.background;
114
118
  var adjustEdge = editConfigModel.adjustEdge;
115
- return ((0, jsx_runtime_1.jsxs)("div", { className: "lf-graph", "flow-id": graphModel.flowId, style: style, children: [(0, jsx_runtime_1.jsxs)(overlay_1.CanvasOverlay, { graphModel: graphModel, dnd: dnd, children: [(0, jsx_runtime_1.jsx)("g", { className: "lf-base", children: (0, lodash_es_1.map)(graphModel.sortElements, function (nodeModel) {
119
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "lf-graph", "flow-id": graphModel.flowId, style: style, children: [(0, jsx_runtime_1.jsxs)(overlay_1.CanvasOverlay, { ref: this.canvasOverlayRef, graphModel: graphModel, dnd: dnd, children: [(0, jsx_runtime_1.jsx)("g", { className: "lf-base", children: (0, lodash_es_1.map)(graphModel.sortElements, function (nodeModel) {
116
120
  return _this.getComponent(nodeModel, graphModel);
117
- }) }), fakeNode ? this.getComponent(fakeNode, graphModel) : ''] }), (0, jsx_runtime_1.jsxs)(overlay_1.ModificationOverlay, { graphModel: graphModel, children: [(0, jsx_runtime_1.jsx)(overlay_1.OutlineOverlay, { graphModel: graphModel }), adjustEdge ? (0, jsx_runtime_1.jsx)(overlay_1.BezierAdjustOverlay, { graphModel: graphModel }) : '', options.snapline !== false ? ((0, jsx_runtime_1.jsx)(overlay_1.SnaplineOverlay, { snaplineModel: snaplineModel })) : ('')] }), (0, jsx_runtime_1.jsx)(overlay_1.ToolOverlay, { graphModel: graphModel, tool: tool }), background && (0, jsx_runtime_1.jsx)(overlay_1.BackgroundOverlay, { background: background }), (0, jsx_runtime_1.jsx)(overlay_1.Grid, { graphModel: graphModel })] }));
121
+ }) }), fakeNode ? this.getComponent(fakeNode, graphModel) : ''] }), (0, jsx_runtime_1.jsxs)(overlay_1.ModificationOverlay, { graphModel: graphModel, children: [(0, jsx_runtime_1.jsx)(overlay_1.OutlineOverlay, { graphModel: graphModel }), adjustEdge ? (0, jsx_runtime_1.jsx)(overlay_1.BezierAdjustOverlay, { graphModel: graphModel }) : '', options.snapline !== false ? ((0, jsx_runtime_1.jsx)(overlay_1.SnaplineOverlay, { snaplineModel: snaplineModel })) : ('')] }), (0, jsx_runtime_1.jsx)(overlay_1.ToolOverlay, { graphModel: graphModel, tool: tool, getCanvasOverlay: this.getCanvasOverlay }), background && (0, jsx_runtime_1.jsx)(overlay_1.BackgroundOverlay, { background: background }), (0, jsx_runtime_1.jsx)(overlay_1.Grid, { graphModel: graphModel })] }));
118
122
  };
119
123
  Graph = __decorate([
120
124
  __1.observer
@@ -139,10 +139,6 @@ var BaseNode = /** @class */ (function (_super) {
139
139
  if (_this.t) {
140
140
  (0, util_1.cancelRaf)(_this.t);
141
141
  }
142
- model.transform = new util_1.TranslateMatrix(-x, -y)
143
- .rotate(model.rotate)
144
- .translate(x, y)
145
- .toString();
146
142
  var moveNodes = selectNodes.map(function (node) { return node.id; });
147
143
  // 未被选中的节点也可以拖动
148
144
  if (moveNodes.indexOf(model.id) === -1) {
@@ -1,10 +1,11 @@
1
1
  import { createElement as h, Component } from 'preact/compat';
2
- import { OutlineOverlay } from '.';
2
+ import { CanvasOverlay, OutlineOverlay } from '.';
3
3
  import { GraphModel } from '../../model';
4
4
  import { Tool } from '../../tool';
5
5
  type IProps = {
6
6
  graphModel: GraphModel;
7
7
  tool: Tool;
8
+ getCanvasOverlay: () => CanvasOverlay | null;
8
9
  };
9
10
  export declare class ToolOverlay extends Component<IProps> {
10
11
  componentDidMount(): void;
@@ -14,6 +15,7 @@ export declare class ToolOverlay extends Component<IProps> {
14
15
  */
15
16
  getTools(): import("preact").VNode<import("../..").IToolProps>[];
16
17
  triggerToolRender(): void;
18
+ zoomHandler: (e: WheelEvent) => void;
17
19
  render(): h.JSX.Element;
18
20
  }
19
21
  export default OutlineOverlay;
@@ -20,6 +20,31 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
20
20
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
21
  return c > 3 && r && Object.defineProperty(target, key, r), r;
22
22
  };
23
+ var __read = (this && this.__read) || function (o, n) {
24
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
25
+ if (!m) return o;
26
+ var i = m.call(o), r, ar = [], e;
27
+ try {
28
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
29
+ }
30
+ catch (error) { e = { error: error }; }
31
+ finally {
32
+ try {
33
+ if (r && !r.done && (m = i["return"])) m.call(i);
34
+ }
35
+ finally { if (e) throw e.error; }
36
+ }
37
+ return ar;
38
+ };
39
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
40
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
41
+ if (ar || !(i in from)) {
42
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
43
+ ar[i] = from[i];
44
+ }
45
+ }
46
+ return to.concat(ar || Array.prototype.slice.call(from));
47
+ };
23
48
  Object.defineProperty(exports, "__esModule", { value: true });
24
49
  exports.ToolOverlay = void 0;
25
50
  var jsx_runtime_1 = require("preact/jsx-runtime");
@@ -29,7 +54,13 @@ var __1 = require("../..");
29
54
  var ToolOverlay = /** @class */ (function (_super) {
30
55
  __extends(ToolOverlay, _super);
31
56
  function ToolOverlay() {
32
- return _super !== null && _super.apply(this, arguments) || this;
57
+ var _this = _super.apply(this, __spreadArray([], __read(arguments), false)) || this;
58
+ _this.zoomHandler = function (e) {
59
+ var _a;
60
+ // TODO 是否应该使用 dispatchEvent 来触发事件
61
+ (_a = _this.props.getCanvasOverlay()) === null || _a === void 0 ? void 0 : _a.zoomHandler(e);
62
+ };
63
+ return _this;
33
64
  }
34
65
  // 在react严格模式下,useEffect会执行两次,但是在LogicFlow内部,则只会触发一次componentDidMount和componentDidUpdate。
35
66
  // 其中第一次componentDidMount对应的graphModel为被丢弃的graphModel, 所以不应该生效。
@@ -67,7 +98,13 @@ var ToolOverlay = /** @class */ (function (_super) {
67
98
  };
68
99
  ToolOverlay.prototype.render = function () {
69
100
  var graphModel = this.props.graphModel;
70
- return ((0, jsx_runtime_1.jsx)("div", { className: "lf-tool-overlay", id: "ToolOverlay_".concat(graphModel.flowId), children: this.getTools() }));
101
+ return ((0, jsx_runtime_1.jsx)("div", { className: "lf-tool-overlay", id: "ToolOverlay_".concat(graphModel.flowId),
102
+ /*
103
+ * 默认情况下该容器设置了 pointer-events: none,不会触发这些事件
104
+ * 只会在容器取消 pointer-events: none 后触发,用于缩放、滚动画布等操作
105
+ * 目前只在 selection-select 插件中使用。为了能在元素内部进行框选,在开启选区后会关闭事件透传。需要手动触发事件
106
+ */
107
+ onWheel: this.zoomHandler, children: this.getTools() }));
71
108
  };
72
109
  ToolOverlay = __decorate([
73
110
  __1.observer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logicflow/core",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "description": "LogicFlow, help you quickly create flowcharts",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
package/src/LogicFlow.tsx CHANGED
@@ -1391,6 +1391,12 @@ export class LogicFlow {
1391
1391
  this.graphModel.destroy()
1392
1392
  this.tool.destroy()
1393
1393
  this.history.destroy()
1394
+ for (const extensionName in this.extension) {
1395
+ const extensionInstance = this.extension[extensionName]
1396
+ if ('destroy' in extensionInstance) {
1397
+ extensionInstance.destroy?.()
1398
+ }
1399
+ }
1394
1400
  }
1395
1401
  }
1396
1402
 
@@ -79,6 +79,8 @@ export enum EventType {
79
79
  EDGE_EXCHANGE_NODE = 'edge:exchange-node',
80
80
 
81
81
  // Anchor events
82
+ ANCHOR_CLICK = 'anchor:click',
83
+ ANCHOR_MOUSEDOWN = 'anchor:mousedown',
82
84
  ANCHOR_DRAGSTART = 'anchor:dragstart',
83
85
  ANCHOR_DRAG = 'anchor:drag',
84
86
  ANCHOR_DROP = 'anchor:drop',
@@ -469,6 +469,14 @@ type AnchorEventArgsPick<T extends 'data' | 'e' | 'nodeModel' | 'edgeModel'> =
469
469
  * 锚点事件
470
470
  */
471
471
  interface AnchorEventArgs {
472
+ /**
473
+ * anchor 锚点 click
474
+ */
475
+ 'anchor:click': AnchorEventArgsPick<'data' | 'e' | 'nodeModel'>
476
+ /**
477
+ * anchor 锚点 mousedown
478
+ */
479
+ 'anchor:mousedown': AnchorEventArgsPick<'data' | 'e' | 'nodeModel'>
472
480
  /**
473
481
  * 开始拖拽锚点
474
482
  */
@@ -63,7 +63,7 @@ export class GraphModel {
63
63
  @observable height: number // 画布高度
64
64
 
65
65
  // 流程图主题配置
66
- theme: LogicFlow.Theme
66
+ @observable theme: LogicFlow.Theme
67
67
  // 网格配置
68
68
  @observable grid: Grid.GridOptions
69
69
  // 事件中心
@@ -1,4 +1,4 @@
1
- import { assign, cloneDeep } from 'lodash-es'
1
+ import { get, assign, cloneDeep } from 'lodash-es'
2
2
  import { action, observable } from 'mobx'
3
3
  import BaseEdgeModel from './BaseEdgeModel'
4
4
  import { BaseNodeModel } from '../node'
@@ -13,7 +13,7 @@ import EdgeConfig = LogicFlow.EdgeConfig
13
13
  export class BezierEdgeModel extends BaseEdgeModel {
14
14
  modelType = ModelType.BEZIER_EDGE
15
15
 
16
- offset!: number
16
+ @observable offset!: number
17
17
  @observable path = ''
18
18
  constructor(data: EdgeConfig, graphModel: GraphModel) {
19
19
  super(data, graphModel)
@@ -21,7 +21,7 @@ export class BezierEdgeModel extends BaseEdgeModel {
21
21
  this.setAttributes()
22
22
  }
23
23
  initEdgeData(data: EdgeConfig): void {
24
- this.offset = 100
24
+ this.offset = get(data, 'properties.offset', 100)
25
25
  super.initEdgeData(data)
26
26
  }
27
27
  getEdgeStyle() {
@@ -1,4 +1,4 @@
1
- import { assign, cloneDeep } from 'lodash-es'
1
+ import { get, assign, cloneDeep } from 'lodash-es'
2
2
  import { observable, action } from 'mobx'
3
3
  import { BaseEdgeModel } from '.'
4
4
  import { BaseNodeModel, RectNodeModel, CircleNodeModel, Model } from '..'
@@ -30,11 +30,11 @@ import AnchorConfig = Model.AnchorConfig
30
30
  export class PolylineEdgeModel extends BaseEdgeModel {
31
31
  modelType = ModelType.POLYLINE_EDGE
32
32
  draggingPointList: Point[] = []
33
- offset?: number
33
+ @observable offset?: number
34
34
  @observable dbClickPosition?: Point
35
35
 
36
36
  initEdgeData(data: LogicFlow.EdgeConfig): void {
37
- this.offset = 30
37
+ this.offset = get(data, 'properties.offset', 30)
38
38
  if (data.pointsList) {
39
39
  this.pointsList = data.pointsList
40
40
  }
@@ -740,6 +740,10 @@ export class BaseNodeModel<P extends PropertiesType = PropertiesType>
740
740
  this.text && this.moveText(0, deltaY)
741
741
  moveY = deltaY
742
742
  }
743
+ this.transform = new TranslateMatrix(-this.x, -this.y)
744
+ .rotate(this.rotate)
745
+ .translate(this.x, this.y)
746
+ .toString()
743
747
  return [moveX, moveY]
744
748
  }
745
749
 
package/src/tool/index.ts CHANGED
@@ -70,7 +70,7 @@ export class Tool {
70
70
  this.toolMap.delete(name)
71
71
  return true
72
72
  }
73
- throw new Error('禁用失败,不存在名为 ${tool} 的工具')
73
+ throw new Error(`禁用失败,不存在名为 ${tool} 的工具`)
74
74
  }
75
75
 
76
76
  @action
@@ -81,7 +81,7 @@ export class Tool {
81
81
  this.disabledToolMap.delete(name)
82
82
  return true
83
83
  }
84
- throw new Error('不存在名为 ${tool} 的工具')
84
+ throw new Error(`不存在名为 ${tool} 的工具`)
85
85
  }
86
86
 
87
87
  getTools() {
package/src/util/node.ts CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  } from '../model'
14
14
  import { SegmentDirection } from '../constant'
15
15
  import { isInSegment } from '../algorithm/edge'
16
+ import { Matrix } from './matrix'
16
17
 
17
18
  import Point = LogicFlow.Point
18
19
  import Direction = LogicFlow.Direction
@@ -112,33 +113,33 @@ export const distance = (
112
113
  ): number => Math.hypot(x1 - x2, y1 - y2)
113
114
 
114
115
  /* 是否在某个节点内,手否进行连接,有offset控制粒度,与outline有关,可以优化 */
115
- export const isInNode = (position: Point, node: BaseNodeModel): boolean => {
116
+ export const isInNode = (
117
+ position: Point,
118
+ node: BaseNodeModel,
119
+ offset = 0,
120
+ ): boolean => {
116
121
  let inNode = false
117
- const offset = 0
118
122
  const bBox = getNodeBBox(node)
123
+ const [x, y] = new Matrix([position.x, position.y, 1])
124
+ .translate(-node.x, -node.y)
125
+ .rotate(-node.rotate)
126
+ .translate(node.x, node.y)[0]
127
+ const reverseRotatedPosition = {
128
+ x,
129
+ y,
130
+ }
119
131
  if (
120
- position.x >= bBox.minX - offset &&
121
- position.x <= bBox.maxX + offset &&
122
- position.y >= bBox.minY - offset &&
123
- position.y <= bBox.maxY + offset
132
+ reverseRotatedPosition.x >= bBox.minX - offset &&
133
+ reverseRotatedPosition.x <= bBox.maxX + offset &&
134
+ reverseRotatedPosition.y >= bBox.minY - offset &&
135
+ reverseRotatedPosition.y <= bBox.maxY + offset
124
136
  ) {
125
137
  inNode = true
126
138
  }
127
139
  return inNode
128
140
  }
129
141
  export const isInNodeBbox = (position: Point, node: BaseNodeModel): boolean => {
130
- let inNode = false
131
- const offset = 5
132
- const bBox = getNodeBBox(node)
133
- if (
134
- position.x >= bBox.minX - offset &&
135
- position.x <= bBox.maxX + offset &&
136
- position.y >= bBox.minY - offset &&
137
- position.y <= bBox.maxY + offset
138
- ) {
139
- inNode = true
140
- }
141
- return inNode
142
+ return isInNode(position, node, 5)
142
143
  }
143
144
 
144
145
  export type NodeBBox = {
@@ -361,15 +361,26 @@ class Anchor extends Component<IProps, IState> {
361
361
 
362
362
  render() {
363
363
  const { startX, startY, endX, endY } = this.state
364
- const {
365
- anchorData: { edgeAddable },
366
- edgeStyle,
367
- } = this.props
364
+ const { anchorData, edgeStyle, nodeModel, graphModel } = this.props
365
+ const { edgeAddable } = anchorData
368
366
  return (
369
367
  // className="lf-anchor" 作为下载时,需要将锚点删除的依据,不要修改类名
370
368
  <g className="lf-anchor">
371
369
  <g
370
+ onClick={(ev) => {
371
+ ev.stopPropagation()
372
+ graphModel.eventCenter.emit(EventType.ANCHOR_CLICK, {
373
+ data: anchorData,
374
+ e: ev!,
375
+ nodeModel,
376
+ })
377
+ }}
372
378
  onMouseDown={(ev) => {
379
+ graphModel.eventCenter.emit(EventType.ANCHOR_MOUSEDOWN, {
380
+ data: anchorData,
381
+ e: ev!,
382
+ nodeModel,
383
+ })
373
384
  if (edgeAddable !== false) {
374
385
  this.dragHandler.handleMouseDown(ev)
375
386
  }
@@ -50,6 +50,7 @@ export class ResizeControl extends Component<
50
50
 
51
51
  // 初始化拖拽工具
52
52
  this.dragHandler = new StepDrag({
53
+ onDragStart: this.onDragStart,
53
54
  onDragging: this.onDragging,
54
55
  onDragEnd: this.onDragEnd,
55
56
  step: graphModel.gridSize,
@@ -317,6 +318,10 @@ export class ResizeControl extends Component<
317
318
  // this.triggerResizeEvent(preNodeData, curNodeData, deltaX, deltaY, this.index, this.nodeModel)
318
319
  }
319
320
 
321
+ onDragStart = () => {
322
+ this.graphModel.selectNodeById(this.nodeModel.id)
323
+ }
324
+
320
325
  onDragging = ({ deltaX, deltaY }: IDragParams) => {
321
326
  const { transformModel } = this.graphModel
322
327
  const [dx, dy] = transformModel.fixDeltaXY(deltaX, deltaY)
@@ -1,4 +1,4 @@
1
- import { Component, ComponentType } from 'preact/compat'
1
+ import { Component, ComponentType, createRef } from 'preact/compat'
2
2
  import { map, throttle } from 'lodash-es'
3
3
  import {
4
4
  CanvasOverlay,
@@ -38,6 +38,10 @@ type ContainerStyle = {
38
38
 
39
39
  @observer
40
40
  class Graph extends Component<IGraphProps> {
41
+ canvasOverlayRef = createRef<CanvasOverlay>()
42
+ getCanvasOverlay = () => {
43
+ return this.canvasOverlayRef.current
44
+ }
41
45
  private handleResize = () => {
42
46
  const { graphModel, options } = this.props
43
47
  const { width, height, isContainerWidth, isContainerHeight } = graphModel
@@ -109,7 +113,11 @@ class Graph extends Component<IGraphProps> {
109
113
  return (
110
114
  <div className="lf-graph" flow-id={graphModel.flowId} style={style}>
111
115
  {/* 元素层 */}
112
- <CanvasOverlay graphModel={graphModel} dnd={dnd}>
116
+ <CanvasOverlay
117
+ ref={this.canvasOverlayRef}
118
+ graphModel={graphModel}
119
+ dnd={dnd}
120
+ >
113
121
  <g className="lf-base">
114
122
  {map(graphModel.sortElements, (nodeModel) =>
115
123
  this.getComponent(nodeModel, graphModel),
@@ -128,7 +136,11 @@ class Graph extends Component<IGraphProps> {
128
136
  )}
129
137
  </ModificationOverlay>
130
138
  {/* 工具层:插件 */}
131
- <ToolOverlay graphModel={graphModel} tool={tool} />
139
+ <ToolOverlay
140
+ graphModel={graphModel}
141
+ tool={tool}
142
+ getCanvasOverlay={this.getCanvasOverlay}
143
+ />
132
144
  {/* 画布背景 */}
133
145
  {background && <BackgroundOverlay background={background} />}
134
146
  {/* 画布网格 */}
@@ -13,7 +13,6 @@ import {
13
13
  isMultipleSelect,
14
14
  cancelRaf,
15
15
  createRaf,
16
- TranslateMatrix,
17
16
  IDragParams,
18
17
  // RotateMatrix,
19
18
  } from '../../util'
@@ -297,11 +296,6 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
297
296
  cancelRaf(this.t)
298
297
  }
299
298
 
300
- model.transform = new TranslateMatrix(-x, -y)
301
- .rotate(model.rotate)
302
- .translate(x, y)
303
- .toString()
304
-
305
299
  let moveNodes = selectNodes.map((node) => node.id)
306
300
  // 未被选中的节点也可以拖动
307
301
  if (moveNodes.indexOf(model.id) === -1) {
@@ -1,5 +1,5 @@
1
1
  import { createElement as h, Component } from 'preact/compat'
2
- import { OutlineOverlay } from '.'
2
+ import { CanvasOverlay, OutlineOverlay } from '.'
3
3
  import { observer } from '../..'
4
4
  import LogicFlow from '../../LogicFlow'
5
5
  import { GraphModel } from '../../model'
@@ -8,6 +8,7 @@ import { Tool } from '../../tool'
8
8
  type IProps = {
9
9
  graphModel: GraphModel
10
10
  tool: Tool
11
+ getCanvasOverlay: () => CanvasOverlay | null
11
12
  }
12
13
 
13
14
  @observer
@@ -52,10 +53,24 @@ export class ToolOverlay extends Component<IProps> {
52
53
  lf.components = [] // 保证extension组件的render只执行一次
53
54
  }
54
55
 
56
+ zoomHandler = (e: WheelEvent) => {
57
+ // TODO 是否应该使用 dispatchEvent 来触发事件
58
+ this.props.getCanvasOverlay()?.zoomHandler(e)
59
+ }
60
+
55
61
  render() {
56
62
  const { graphModel } = this.props
57
63
  return (
58
- <div className="lf-tool-overlay" id={`ToolOverlay_${graphModel.flowId}`}>
64
+ <div
65
+ className="lf-tool-overlay"
66
+ id={`ToolOverlay_${graphModel.flowId}`}
67
+ /*
68
+ * 默认情况下该容器设置了 pointer-events: none,不会触发这些事件
69
+ * 只会在容器取消 pointer-events: none 后触发,用于缩放、滚动画布等操作
70
+ * 目前只在 selection-select 插件中使用。为了能在元素内部进行框选,在开启选区后会关闭事件透传。需要手动触发事件
71
+ */
72
+ onWheel={this.zoomHandler}
73
+ >
59
74
  {this.getTools()}
60
75
  </div>
61
76
  )