From ca2830462cecc83c202f5de8c62964c6aecc14a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 09:11:07 +0000 Subject: [PATCH 1/2] Initial plan From ec19b156690d73fa8e52b8538989e385cc70af7f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 09:16:19 +0000 Subject: [PATCH 2/2] docs: add three edge rendering forms and operation points documentation (zh/en) Co-authored-by: CraneReturn <127602190+CraneReturn@users.noreply.github.com> --- sites/docs/docs/tutorial/basic/edge.en.md | 159 ++++++++++++++++++++++ sites/docs/docs/tutorial/basic/edge.zh.md | 159 ++++++++++++++++++++++ 2 files changed, 318 insertions(+) diff --git a/sites/docs/docs/tutorial/basic/edge.en.md b/sites/docs/docs/tutorial/basic/edge.en.md index 81a0adeb8..9a1d3be69 100644 --- a/sites/docs/docs/tutorial/basic/edge.en.md +++ b/sites/docs/docs/tutorial/basic/edge.en.md @@ -18,6 +18,165 @@ The effect is as follows: +## Three Edge Rendering Forms + +### Line + +Line is the simplest edge type. It renders directly using an SVG `` element connecting the start point to the end point. + +**Rendering characteristics**: + +- Uses an SVG `` element where `x1/y1` is the start point and `x2/y2` is the end point. +- Simplest path calculation: only `startPoint` and `endPoint` coordinates are needed. +- Click area (AppendWidth): a rectangle is computed on both sides of the line so that thin lines are easier to click. + +```tsx | pure +// LineEdge getEdge core rendering +getEdge() { + const { model } = this.props + const { startPoint, endPoint } = model + return ( + + ) +} +``` + +### Polyline + +Polyline (orthogonal polyline) is a multi-segment line where every segment is either horizontal or vertical. It is rendered using an SVG `` element. + +**Rendering characteristics**: + +- Uses an SVG `` element with all waypoints passed in the `points` attribute (format: `"x1,y1 x2,y2 x3,y3 ..."`). +- Complex path calculation: uses an A* algorithm with Manhattan distance to automatically route around nodes; results are stored in `pointsList`. +- Click area (AppendWidth): each segment has its own rectangular hit region that are all combined together. + +```tsx | pure +// PolylineEdge getEdge core rendering +getEdge() { + const { model } = this.props + const { points } = model // "x1,y1 x2,y2 x3,y3 ..." + return ( + + ) +} +``` + +### Bezier + +The bezier edge is a cubic Bézier curve rendered using an SVG `` element with the `M...C...` command. + +**Rendering characteristics**: + +- Uses an SVG `` element. The path format is `M startX startY C sNextX sNextY, ePreX ePreY, endX endY`. +- `pointsList` always contains exactly 4 points: **start**, **start control point (sNext)**, **end control point (ePre)**, **end**. +- The initial positions of the two control points are calculated automatically based on the source and target node positions so the curve avoids overlapping node borders. +- Click area (AppendWidth): a transparent curve with `strokeWidth=10` is drawn on top of the actual path to enlarge the hit area. + +```tsx | pure +// BezierEdgeModel path generation +private getPath(points: Point[]): string { + const [start, sNext, ePre, end] = points + return `M ${start.x} ${start.y} + C ${sNext.x} ${sNext.y}, + ${ePre.x} ${ePre.y}, + ${end.x} ${end.y}` +} +``` + +## Operation Point Differences + +"Operation points" are the interactive handles shown when an edge is selected, used to adjust its shape. All three edge types support common start/end adjustment points, but each type also has its own unique handles. + +### Common: Start/End Adjustment Points + +All three edge types support start/end adjustment points. Enable them at initialization with `adjustEdgeStartAndEnd`: + +```tsx | pure +const lf = new LogicFlow({ + adjustEdgeStartAndEnd: true, // Enable start/end point adjustment +}) +``` + +When enabled, a circular handle appears at both the **start** and **end** of a selected edge. Drag either handle to reconnect the edge to a different anchor on another node. + +### Line Operation Points + +A line has **only** start/end adjustment points. There is no way to change the intermediate path because a straight line between two points is unique. + +| Operation Point | Description | +|----------------|-------------| +| Start adjustment (SOURCE) | Drag to reconnect to a different node anchor | +| End adjustment (TARGET) | Drag to reconnect to a different node anchor | + +### Polyline Operation Points + +In addition to start/end adjustment points, a polyline also supports **segment dragging**. Each segment has a transparent draggable region (generated by `getAppendWidth`): + +- **Horizontal segments**: can only be dragged vertically (move the segment up/down); cursor becomes `ns-resize`. +- **Vertical segments**: can only be dragged horizontally (move the segment left/right); cursor becomes `ew-resize`. + +Use `adjustEdgeMiddle` to restrict dragging to middle segments only, preventing the first and last segments (which connect to nodes) from being accidentally moved: + +```tsx | pure +const lf = new LogicFlow({ + adjustEdgeStartAndEnd: true, + adjustEdgeMiddle: true, // Only middle segments can be dragged +}) +``` + +| Operation Point | Description | +|----------------|-------------| +| Start adjustment (SOURCE) | Drag to reconnect to a different node anchor | +| End adjustment (TARGET) | Drag to reconnect to a different node anchor | +| Segment drag regions | Translate the segment horizontally or vertically | + +### Bezier Operation Points + +In addition to start/end adjustment points, two **Bézier control points** (`sNext` and `ePre`) and their guide lines appear when a bezier edge is selected (rendered by `BezierAdjustOverlay`): + +- **sNext** (start control point): connected to the start point by a guide line; drag it to change the curvature direction and magnitude near the start. +- **ePre** (end control point): connected to the end point by a guide line; drag it to change the curvature direction and magnitude near the end. +- The two control points are independent of each other. + +```tsx | pure +// BezierAdjustOverlay control-point rendering logic +getBezierAdjust(bezier: BezierEdgeModel, graphModel: GraphModel) { + const [start, sNext, ePre, end] = getBezierPoints(bezier.path) + return [ + // Start side: guide line + sNext control point + , + , + // End side: guide line + ePre control point + , + , + ] +} +``` + +| Operation Point | Description | +|----------------|-------------| +| Start adjustment (SOURCE) | Drag to reconnect to a different node anchor | +| End adjustment (TARGET) | Drag to reconnect to a different node anchor | +| sNext (start control point) | Drag to change curve shape near the start | +| ePre (end control point) | Drag to change curve shape near the end | + +### Operation Point Comparison + +| Operation Point Type | Line | Polyline | Bezier | +|---------------------|:----:|:--------:|:------:| +| Start adjustment (SOURCE) | ✓ | ✓ | ✓ | +| End adjustment (TARGET) | ✓ | ✓ | ✓ | +| Segment drag (move segments individually) | ✗ | ✓ | ✗ | +| Bézier control points (sNext / ePre) | ✗ | ✗ | ✓ | + ## Selecting built-in edges inherited by custom edges ```tsx | pure diff --git a/sites/docs/docs/tutorial/basic/edge.zh.md b/sites/docs/docs/tutorial/basic/edge.zh.md index 4d128ad3d..1c1b38788 100644 --- a/sites/docs/docs/tutorial/basic/edge.zh.md +++ b/sites/docs/docs/tutorial/basic/edge.zh.md @@ -18,6 +18,165 @@ toc: content +## 三种边的渲染形式 + +### 直线(line) + +直线是最简单的边类型,通过 SVG 的 `` 标签直接连接起点与终点,路径唯一确定。 + +**渲染特点**: + +- 底层使用 SVG `` 元素,`x1/y1` 为起点,`x2/y2` 为终点。 +- 路径计算最简:只需 `startPoint` 和 `endPoint` 两个坐标。 +- 选中区域(AppendWidth):以直线为中轴,向两侧各扩展一定宽度,形成矩形点击区,方便用户选中细线。 + +```tsx | pure +// LineEdge 的 getEdge 核心渲染 +getEdge() { + const { model } = this.props + const { startPoint, endPoint } = model + return ( + + ) +} +``` + +### 折线(polyline) + +折线(直角折线)是所有线段均为水平或垂直方向的多段线,通过 SVG 的 `` 标签渲染多个折点。 + +**渲染特点**: + +- 底层使用 SVG `` 元素,通过 `points` 属性传入所有折点坐标(格式:`"x1,y1 x2,y2 x3,y3 ..."`)。 +- 路径计算复杂:采用 A* 算法结合曼哈顿距离,自动绕过节点计算最优正交路径,结果存储在 `pointsList` 中。 +- 选中区域(AppendWidth):将折线拆分为每段线段,对每段单独计算矩形扩展区域并叠加。 + +```tsx | pure +// PolylineEdge 的 getEdge 核心渲染 +getEdge() { + const { model } = this.props + const { points } = model // "x1,y1 x2,y2 x3,y3 ..." + return ( + + ) +} +``` + +### 贝塞尔曲线(bezier) + +贝塞尔曲线是三次贝塞尔曲线,通过 SVG `` 的 `M...C...` 命令绘制光滑曲线。 + +**渲染特点**: + +- 底层使用 SVG `` 元素,路径格式为 `M startX startY C sNextX sNextY, ePreX ePreY, endX endY`。 +- `pointsList` 固定包含 4 个点:**起点**、**起点控制点(sNext)**、**终点控制点(ePre)**、**终点**。 +- 控制点的初始位置根据起终点所在节点的方位自动计算,使曲线尽量不与节点边框重叠。 +- 选中区域(AppendWidth):在相同路径上绘制一条宽度为 10、颜色透明的曲线,扩大点击范围。 + +```tsx | pure +// BezierEdgeModel 的路径生成 +private getPath(points: Point[]): string { + const [start, sNext, ePre, end] = points + return `M ${start.x} ${start.y} + C ${sNext.x} ${sNext.y}, + ${ePre.x} ${ePre.y}, + ${end.x} ${end.y}` +} +``` + +## 三种边的操作点区别 + +"操作点"是指边被选中后,用于调整边形态的交互控件。三种边均支持公共的起终点调整点,但各自还有独特的操作点。 + +### 公共操作:起终点调整点 + +三种边都支持起终点调整点,需在初始化时开启 `adjustEdgeStartAndEnd`: + +```tsx | pure +const lf = new LogicFlow({ + adjustEdgeStartAndEnd: true, // 开启起终点调整功能 +}) +``` + +开启后,选中边时在**起点**和**终点**各显示一个圆形调整点,拖拽可将边重新连接到其他节点的锚点。 + +### 直线(line)的操作点 + +直线**仅有**起终点调整点,无法改变中间路径——因为两点之间直线唯一,没有可调整的中间段。 + +| 操作点 | 说明 | +|--------|------| +| 起点调整点(SOURCE) | 拖拽重新连接到其他节点锚点 | +| 终点调整点(TARGET) | 拖拽重新连接到其他节点锚点 | + +### 折线(polyline)的操作点 + +折线除起终点调整点外,还支持**线段拖拽**。每个线段均有透明可拖拽区域(由 `getAppendWidth` 生成): + +- **水平线段**:只能沿垂直方向拖拽(纵向平移该段);光标变为 `ns-resize`。 +- **垂直线段**:只能沿水平方向拖拽(横向平移该段);光标变为 `ew-resize`。 + +通过配置 `adjustEdgeMiddle` 可进一步限制只允许拖拽中间线段,防止连接节点的首尾段被意外移动: + +```tsx | pure +const lf = new LogicFlow({ + adjustEdgeStartAndEnd: true, + adjustEdgeMiddle: true, // 仅允许拖拽中间线段,首尾线段不可拖拽 +}) +``` + +| 操作点 | 说明 | +|--------|------| +| 起点调整点(SOURCE) | 拖拽重新连接到其他节点锚点 | +| 终点调整点(TARGET) | 拖拽重新连接到其他节点锚点 | +| 各线段拖拽区域 | 沿水平或垂直方向平移对应线段 | + +### 贝塞尔曲线(bezier)的操作点 + +贝塞尔曲线除起终点调整点外,选中时还会显示**两个贝塞尔控制点**(`sNext` 和 `ePre`)及其辅助连线(由 `BezierAdjustOverlay` 渲染): + +- **sNext**(起点控制点):通过辅助线与起点相连,拖拽可改变曲线起点侧的弯曲方向和幅度。 +- **ePre**(终点控制点):通过辅助线与终点相连,拖拽可改变曲线终点侧的弯曲方向和幅度。 +- 两个控制点相互独立,可以单独调节。 + +```tsx | pure +// BezierAdjustOverlay 中的控制点渲染逻辑 +getBezierAdjust(bezier: BezierEdgeModel, graphModel: GraphModel) { + const [start, sNext, ePre, end] = getBezierPoints(bezier.path) + return [ + // 起点侧:辅助线 + sNext 控制点 + , + , + // 终点侧:辅助线 + ePre 控制点 + , + , + ] +} +``` + +| 操作点 | 说明 | +|--------|------| +| 起点调整点(SOURCE) | 拖拽重新连接到其他节点锚点 | +| 终点调整点(TARGET) | 拖拽重新连接到其他节点锚点 | +| sNext(起点控制点) | 拖拽改变曲线起点侧的弯曲形态 | +| ePre(终点控制点) | 拖拽改变曲线终点侧的弯曲形态 | + +### 操作点对比 + +| 操作点类型 | 直线 | 折线 | 贝塞尔曲线 | +|-----------|:----:|:----:|:----------:| +| 起点调整(SOURCE) | ✓ | ✓ | ✓ | +| 终点调整(TARGET) | ✓ | ✓ | ✓ | +| 线段拖拽(逐段移动) | ✗ | ✓ | ✗ | +| 贝塞尔控制点(sNext / ePre) | ✗ | ✗ | ✓ | + ## 选择自定义边继承的内置边 ```tsx | pure