Skip to content

Commit c208758

Browse files
authored
feat(free-layout): output port support left location and refactor arrow render (#766)
1 parent f54a3fe commit c208758

10 files changed

Lines changed: 85 additions & 83 deletions

File tree

packages/canvas-engine/free-layout-core/src/entities/workflow-line-entity.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,9 @@ export class WorkflowLineEntity extends Entity<WorkflowLineEntityOpts> {
435435
return this.linesManager.isDisabledLine(this, this.uiState.disabled);
436436
}
437437

438-
/** 是否竖向 */
438+
/**
439+
* @deprecated
440+
*/
439441
get vertical(): boolean {
440442
const fromLocation = this.fromPort.location;
441443
const toLocation = this.toPort?.location;

packages/canvas-engine/free-layout-core/src/entity-datas/workflow-node-ports-data.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { FlowNodeRenderData } from '@flowgram.ai/document';
88
import { EntityData, SizeData } from '@flowgram.ai/core';
99

1010
import { type WorkflowPortType, getPortEntityId } from '../utils/statics';
11-
import { type LinePoint, type WorkflowNodeMeta } from '../typings';
11+
import { type LinePoint, LinePointLocation, type WorkflowNodeMeta } from '../typings';
1212
import { WorkflowPortEntity } from '../entities/workflow-port-entity';
1313
import { type WorkflowNodeEntity, type WorkflowPort, type WorkflowPorts } from '../entities';
1414

@@ -96,6 +96,7 @@ export class WorkflowNodePortsData extends EntityData {
9696
...Array.from(elements).map((element) => ({
9797
portID: element.getAttribute('data-port-id')!,
9898
type: element.getAttribute('data-port-type')! as WorkflowPortType,
99+
location: element.getAttribute('data-port-location')! as LinePointLocation,
99100
targetElement: element,
100101
}))
101102
);

packages/canvas-engine/free-layout-core/src/service/workflow-drag-service.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import { WorkflowLinesManager } from '../workflow-lines-manager';
3838
import { WorkflowDocumentOptions } from '../workflow-document-option';
3939
import { WorkflowDocument } from '../workflow-document';
4040
import { LineEventProps, NodesDragEvent, OnDragLineEnd } from '../typings/workflow-drag';
41-
import { type WorkflowNodeJSON, type WorkflowNodeMeta } from '../typings';
41+
import { LinePointLocation, type WorkflowNodeJSON, type WorkflowNodeMeta } from '../typings';
4242
import { WorkflowNodePortsData } from '../entity-datas';
4343
import {
4444
type WorkflowLineEntity,
@@ -67,6 +67,19 @@ function checkDragSuccess(
6767
return false;
6868
}
6969

70+
function reverseLocation(sourceLocation: LinePointLocation): LinePointLocation {
71+
switch (sourceLocation) {
72+
case 'bottom':
73+
return 'top';
74+
case 'left':
75+
return 'right';
76+
case 'top':
77+
return 'bottom';
78+
case 'right':
79+
return 'left';
80+
}
81+
}
82+
7083
@injectable()
7184
export class WorkflowDragService {
7285
@inject(PlaygroundConfigEntity)
@@ -669,7 +682,7 @@ export class WorkflowDragService {
669682
line.drawingTo = {
670683
x: dragPos.x,
671684
y: dragPos.y,
672-
location: line.fromPort.location === 'right' ? 'left' : 'top',
685+
location: reverseLocation(line.fromPort.location),
673686
};
674687
}
675688

packages/plugins/free-lines-plugin/src/components/workflow-line-render/arrow.tsx

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,37 @@
55

66
import React from 'react';
77

8+
import { IPoint } from '@flowgram.ai/utils';
9+
import { LinePointLocation } from '@flowgram.ai/free-layout-core';
10+
811
import { type ArrowRendererProps } from '../../types/arrow-renderer';
912
import { LINE_OFFSET } from '../../constants/lines';
1013

11-
export function ArrowRenderer({
12-
id,
13-
pos,
14-
reverseArrow,
15-
strokeWidth,
16-
vertical,
17-
hide,
18-
}: ArrowRendererProps) {
14+
function getArrowPath(pos: IPoint, location: LinePointLocation): string {
15+
switch (location) {
16+
case 'left':
17+
return `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${
18+
pos.x - LINE_OFFSET
19+
},${pos.y + LINE_OFFSET}`;
20+
case 'right':
21+
return `M ${pos.x + LINE_OFFSET},${pos.y + LINE_OFFSET} L ${pos.x},${pos.y} L ${
22+
pos.x + LINE_OFFSET
23+
},${pos.y - LINE_OFFSET}`;
24+
case 'bottom':
25+
return `M ${pos.x - LINE_OFFSET},${pos.y + LINE_OFFSET} L ${pos.x},${pos.y} L ${
26+
pos.x + LINE_OFFSET
27+
},${pos.y + LINE_OFFSET}`;
28+
case 'top':
29+
return `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${
30+
pos.x + LINE_OFFSET
31+
},${pos.y - LINE_OFFSET}`;
32+
}
33+
}
34+
export function ArrowRenderer({ id, pos, strokeWidth, location, hide }: ArrowRendererProps) {
1935
if (hide) {
2036
return null;
2137
}
22-
const arrowPath = vertical
23-
? reverseArrow
24-
? `M ${pos.x - LINE_OFFSET},${pos.y} L ${pos.x},${pos.y - LINE_OFFSET} L ${
25-
pos.x + LINE_OFFSET
26-
},${pos.y}`
27-
: `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${
28-
pos.x + LINE_OFFSET
29-
},${pos.y - LINE_OFFSET}`
30-
: reverseArrow
31-
? `M ${pos.x},${pos.y + LINE_OFFSET} L ${pos.x - LINE_OFFSET},${pos.y} L ${pos.x},${
32-
pos.y - LINE_OFFSET
33-
}`
34-
: `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${
35-
pos.x - LINE_OFFSET
36-
},${pos.y + LINE_OFFSET}`;
38+
const arrowPath = getArrowPath(pos, location);
3739

3840
return (
3941
<path

packages/plugins/free-lines-plugin/src/components/workflow-line-render/line-svg.tsx

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@ import React from 'react';
77

88
import clsx from 'clsx';
99
import { type IPoint } from '@flowgram.ai/utils';
10-
import { POINT_RADIUS } from '@flowgram.ai/free-layout-core';
1110
import { WorkflowLineRenderData } from '@flowgram.ai/free-layout-core';
1211

1312
import { type ArrowRendererComponent } from '../../types/arrow-renderer';
1413
import { LineRenderProps } from '../../type';
14+
import { posWithShrink } from '../../contributions/utils';
1515
import { STROKE_WIDTH_SLECTED, STROKE_WIDTH } from '../../constants/points';
16-
import { LINE_OFFSET } from '../../constants/lines';
1716
import { LineStyle } from './index.style';
1817
import { ArrowRenderer } from './arrow';
1918

@@ -36,14 +35,8 @@ export const LineSVG = (props: LineRenderProps) => {
3635
const toPos = toRelative(position.to);
3736

3837
// 箭头位置计算
39-
const arrowToPos: IPoint =
40-
position.to.location === 'top'
41-
? { x: toPos.x, y: toPos.y - POINT_RADIUS }
42-
: { x: toPos.x - POINT_RADIUS, y: toPos.y };
43-
const arrowFromPos: IPoint =
44-
position.from.location === 'bottom'
45-
? { x: fromPos.x, y: fromPos.y + POINT_RADIUS + LINE_OFFSET }
46-
: { x: fromPos.x + POINT_RADIUS + LINE_OFFSET, y: fromPos.y };
38+
const arrowToPos: IPoint = posWithShrink(toPos, position.to.location, line.uiState.shrink);
39+
const arrowFromPos: IPoint = posWithShrink(fromPos, position.from.location, line.uiState.shrink);
4740

4841
const strokeWidth = selected
4942
? line.uiState.strokeWidthSelected ?? STROKE_WIDTH_SLECTED
@@ -95,10 +88,9 @@ export const LineSVG = (props: LineRenderProps) => {
9588
{path}
9689
<ArrowComponent
9790
id={strokeID}
98-
reverseArrow={reverse}
9991
pos={reverse ? arrowFromPos : arrowToPos}
10092
strokeWidth={strokeWidth}
101-
vertical={vertical}
93+
location={reverse ? position.from.location : position.to.location}
10294
hide={hideArrow}
10395
line={line}
10496
/>

packages/plugins/free-lines-plugin/src/contributions/bezier/index.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
} from '@flowgram.ai/free-layout-core';
1414
import { LineType } from '@flowgram.ai/free-layout-core';
1515

16-
import { toRelative } from '../utils';
16+
import { posWithShrink, toRelative } from '../utils';
1717
import { getBezierControlPoints } from './bezier-controls';
1818

1919
export interface BezierData {
@@ -111,15 +111,9 @@ export class WorkflowBezierLineContribution implements WorkflowLineRenderContrib
111111
const controls = params.controls.map((c) => toRelative(c, bbox));
112112
const shrink = this.entity.uiState.shrink;
113113

114-
const renderFromPos: IPoint =
115-
params.fromPos.location === 'bottom'
116-
? { x: fromPos.x, y: fromPos.y + shrink }
117-
: { x: fromPos.x + shrink, y: fromPos.y };
114+
const renderFromPos: IPoint = posWithShrink(fromPos, params.fromPos.location, shrink);
118115

119-
const renderToPos: IPoint =
120-
params.toPos.location === 'top'
121-
? { x: toPos.x, y: toPos.y - shrink }
122-
: { x: toPos.x - shrink, y: toPos.y };
116+
const renderToPos: IPoint = posWithShrink(toPos, params.toPos.location, shrink);
123117

124118
const controlPoints = controls.map((s) => `${s.x} ${s.y}`).join(',');
125119
return `M${renderFromPos.x} ${renderFromPos.y} C ${controlPoints}, ${renderToPos.x} ${renderToPos.y}`;

packages/plugins/free-lines-plugin/src/contributions/fold/index.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
} from '@flowgram.ai/free-layout-core';
1313
import { LineType } from '@flowgram.ai/free-layout-core';
1414

15-
import { toRelative } from '../utils';
15+
import { posWithShrink, toRelative } from '../utils';
1616
import { FoldLine } from './fold-line';
1717

1818
export interface FoldData {
@@ -60,24 +60,16 @@ export class WorkflowFoldLineContribution implements WorkflowLineRenderContribut
6060
const shrink = this.entity.uiState.shrink;
6161

6262
// 根据方向预先计算源点和目标点的偏移
63-
const sourceOffset = {
64-
x: fromPos.location === 'bottom' ? 0 : shrink,
65-
y: fromPos.location === 'bottom' ? shrink : 0,
66-
};
67-
const targetOffset = {
68-
x: toPos.location === 'top' ? 0 : -shrink,
69-
y: toPos.location === 'top' ? -shrink : 0,
70-
};
63+
const source = posWithShrink(fromPos, fromPos.location, shrink);
64+
const target = posWithShrink(toPos, toPos.location, shrink);
7165

7266
const { points, center } = FoldLine.getPoints({
7367
source: {
74-
x: fromPos.x + sourceOffset.x,
75-
y: fromPos.y + sourceOffset.y,
68+
...source,
7669
location: fromPos.location,
7770
},
7871
target: {
79-
x: toPos.x + targetOffset.x,
80-
y: toPos.y + targetOffset.y,
72+
...target,
8173
location: toPos.location,
8274
},
8375
});

packages/plugins/free-lines-plugin/src/contributions/straight/index.ts

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515

1616
import { LINE_PADDING } from '../../constants/lines';
1717
import { projectPointOnLine } from './point-on-line';
18+
import { posWithShrink } from '../utils';
1819

1920
export interface StraightData {
2021
points: IPoint[];
@@ -62,25 +63,10 @@ export class WorkflowStraightLineContribution implements WorkflowLineRenderContr
6263
const shrink = this.entity.uiState.shrink;
6364

6465
// 根据方向预先计算源点和目标点的偏移
65-
const sourceOffset = {
66-
x: fromPos.location === 'bottom' ? 0 : shrink,
67-
y: fromPos.location === 'bottom' ? shrink : 0,
68-
};
69-
const targetOffset = {
70-
x: toPos.location === 'top' ? 0 : -shrink,
71-
y: toPos.location === 'top' ? -shrink : 0,
72-
};
66+
const source = posWithShrink(fromPos, fromPos.location, shrink);
67+
const target = posWithShrink(toPos, toPos.location, shrink);
7368

74-
const points = [
75-
{
76-
x: fromPos.x + sourceOffset.x,
77-
y: fromPos.y + sourceOffset.y,
78-
},
79-
{
80-
x: toPos.x + targetOffset.x,
81-
y: toPos.y + targetOffset.y,
82-
},
83-
];
69+
const points = [source, target];
8470

8571
const bbox = Rectangle.createRectangleWithTwoPoints(points[0], points[1]);
8672

packages/plugins/free-lines-plugin/src/contributions/utils.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
import { IPoint, Rectangle } from '@flowgram.ai/utils';
7+
import { LinePointLocation } from '@flowgram.ai/free-layout-core';
78

89
import { LINE_PADDING } from '../constants/lines';
910

@@ -13,3 +14,24 @@ export function toRelative(p: IPoint, bbox: Rectangle): IPoint {
1314
y: p.y - bbox.y + LINE_PADDING,
1415
};
1516
}
17+
18+
export function getShrinkOffset(location: LinePointLocation, shrink: number): IPoint {
19+
switch (location) {
20+
case 'left':
21+
return { x: -shrink, y: 0 };
22+
case 'right':
23+
return { x: shrink, y: 0 };
24+
case 'bottom':
25+
return { x: 0, y: shrink };
26+
case 'top':
27+
return { x: 0, y: -shrink };
28+
}
29+
}
30+
31+
export function posWithShrink(pos: IPoint, location: LinePointLocation, shrink: number): IPoint {
32+
const offset = getShrinkOffset(location, shrink);
33+
return {
34+
x: pos.x + offset.x,
35+
y: pos.y + offset.y,
36+
};
37+
}

packages/plugins/free-lines-plugin/src/types/arrow-renderer.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import React from 'react';
77

88
import { type IPoint } from '@flowgram.ai/utils';
9+
import { LinePointLocation } from '@flowgram.ai/free-layout-core/src';
910
import { type WorkflowLineEntity } from '@flowgram.ai/free-layout-core';
1011

1112
/**
@@ -16,12 +17,9 @@ export interface ArrowRendererProps {
1617
id: string;
1718
/** 箭头位置 */
1819
pos: IPoint;
19-
/** 是否反转箭头方向 */
20-
reverseArrow: boolean;
20+
location: LinePointLocation;
2121
/** 描边宽度 */
2222
strokeWidth: number;
23-
/** 是否为垂直方向 */
24-
vertical?: boolean;
2523
/** 是否隐藏箭头 */
2624
hide?: boolean;
2725
/** 线条实体,提供更多上下文信息 */

0 commit comments

Comments
 (0)