leafer-connector 0.1.0
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.
- package/LICENSE +23 -0
- package/README.md +386 -0
- package/dist/cjs/Connector.cjs +806 -0
- package/dist/cjs/Connector.js.map +1 -0
- package/dist/cjs/anchors.cjs +140 -0
- package/dist/cjs/anchors.js.map +1 -0
- package/dist/cjs/bezier.cjs +101 -0
- package/dist/cjs/bezier.js.map +1 -0
- package/dist/cjs/index.cjs +21 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/route.cjs +185 -0
- package/dist/cjs/route.js.map +1 -0
- package/dist/cjs/types.cjs +3 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/utils.cjs +11 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/esm/Connector.d.ts +49 -0
- package/dist/esm/Connector.d.ts.map +1 -0
- package/dist/esm/Connector.js +802 -0
- package/dist/esm/Connector.js.map +1 -0
- package/dist/esm/anchors.d.ts +9 -0
- package/dist/esm/anchors.d.ts.map +1 -0
- package/dist/esm/anchors.js +132 -0
- package/dist/esm/anchors.js.map +1 -0
- package/dist/esm/bezier.d.ts +10 -0
- package/dist/esm/bezier.d.ts.map +1 -0
- package/dist/esm/bezier.js +95 -0
- package/dist/esm/bezier.js.map +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/route.d.ts +23 -0
- package/dist/esm/route.d.ts.map +1 -0
- package/dist/esm/route.js +179 -0
- package/dist/esm/route.js.map +1 -0
- package/dist/esm/types.d.ts +202 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/utils.d.ts +3 -0
- package/dist/esm/utils.d.ts.map +1 -0
- package/dist/esm/utils.js +7 -0
- package/dist/esm/utils.js.map +1 -0
- package/package.json +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
# leafer-connector
|
|
2
|
+
|
|
3
|
+
基于 LeaferJS(通过 `leafer-editor`)实现的连接线(Connector / Edge)组件,面向“白板 / 流程图 / 节点图”场景。
|
|
4
|
+
|
|
5
|
+
你可以把它理解成:**给两个 `IUI` 节点自动画出一条“像流程图工具一样”的连线**,并支持 label、协同等能力。
|
|
6
|
+
|
|
7
|
+
## 能力概览
|
|
8
|
+
|
|
9
|
+
- **连接 2 个节点**:`from/to: IUI`
|
|
10
|
+
- **端点模型**:`padding / margin / side(auto) / percent / linkPoint`
|
|
11
|
+
- **路由类型**:`orthogonal / bezier / straight / custom`
|
|
12
|
+
- **样式**:`stroke / strokeWidth / dashPattern / startArrow / endArrow`
|
|
13
|
+
- **缩放策略**:`scaleMode: world | pixel`(线宽/箭头是否随 zoom 缩放)
|
|
14
|
+
- **交互**:双击连线创建/编辑 label(label 永远在路径中点)
|
|
15
|
+
- **协同/程序更新**:`updateMode="render"` + `renderThrottleMs`
|
|
16
|
+
- **状态同步**:`getState/setState` + `onChange/onLabelChange` 输出 diff
|
|
17
|
+
|
|
18
|
+
## 安装
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add leafer-connector leafer-editor
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
> `leafer-editor` 为 peerDependency,需要业务侧安装并锁定版本。
|
|
25
|
+
|
|
26
|
+
## 快速开始(最小可用)
|
|
27
|
+
|
|
28
|
+
最小输入参数只有:`app` + `from/to`。
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { App, Rect } from "leafer-editor";
|
|
32
|
+
import { Connector } from "leafer-connector";
|
|
33
|
+
|
|
34
|
+
const app = new App({ view: container, editor: {} });
|
|
35
|
+
|
|
36
|
+
const a = new Rect({ x: 100, y: 100, width: 200, height: 160, fill: "#32cd79", draggable: true });
|
|
37
|
+
const b = new Rect({ x: 520, y: 280, width: 220, height: 160, fill: "#3b82f6", draggable: true });
|
|
38
|
+
|
|
39
|
+
const edge = new Connector(app, { from: a, to: b });
|
|
40
|
+
app.tree.add([a, b, edge]);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 路由示例
|
|
44
|
+
|
|
45
|
+
### 正交(orthogonal)
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
const edge = new Connector(app, {
|
|
49
|
+
from: a,
|
|
50
|
+
to: b,
|
|
51
|
+
routeType: "orthogonal",
|
|
52
|
+
cornerRadius: 16,
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+

|
|
56
|
+
|
|
57
|
+
### 贝塞尔(bezier)
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
const edge = new Connector(app, {
|
|
61
|
+
from: a,
|
|
62
|
+
to: b,
|
|
63
|
+
routeType: "bezier",
|
|
64
|
+
bezierCurvature: 0.6,
|
|
65
|
+
routeOptions: {
|
|
66
|
+
// 0:尽量保持贝塞尔;140:近距离自动降级正交更稳定
|
|
67
|
+
bezierFallbackDistance: 0,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+

|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
### 直线(straight)
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const edge = new Connector(app, {
|
|
78
|
+
from: a,
|
|
79
|
+
to: b,
|
|
80
|
+
routeType: "straight",
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+

|
|
84
|
+
|
|
85
|
+
### 自定义(custom + onDraw)
|
|
86
|
+
|
|
87
|
+
你可以在组件算出默认结果后,通过 `onDraw` 覆盖:
|
|
88
|
+
|
|
89
|
+
- **覆盖 `points`**(world 坐标):组件会基于 points 重新生成圆角路径并更新 label 中点
|
|
90
|
+
- **覆盖 `path`**(world 坐标 SVG path):支持 `M/L/C/Q/Z`(绝对坐标)。若只覆盖 path 不覆盖 points,label 会沿用默认中点
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
const edge = new Connector(app, {
|
|
94
|
+
from: a,
|
|
95
|
+
to: b,
|
|
96
|
+
routeType: "custom",
|
|
97
|
+
onDraw: ({ s, e, defaultResult }) => {
|
|
98
|
+
// 1) 直接用默认结果
|
|
99
|
+
// return
|
|
100
|
+
|
|
101
|
+
// 2) 覆盖 points(world)
|
|
102
|
+
// return { points: [s.linkPoint, s.paddingPoint, e.paddingPoint, e.linkPoint] }
|
|
103
|
+
|
|
104
|
+
// 3) 覆盖 path(world,M/L/C/Q/Z)
|
|
105
|
+
return { path: defaultResult.path };
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+

|
|
110
|
+
|
|
111
|
+
## label(连线文字)示例
|
|
112
|
+
|
|
113
|
+
### 默认 label(有背景遮挡)
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
const edge = new Connector(app, {
|
|
117
|
+
from: a,
|
|
118
|
+
to: b,
|
|
119
|
+
label: { text: "Hello", editable: true },
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+

|
|
123
|
+
|
|
124
|
+
### 自定义 label 样式
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
const edge = new Connector(app, {
|
|
128
|
+
from: a,
|
|
129
|
+
to: b,
|
|
130
|
+
label: {
|
|
131
|
+
text: "关系",
|
|
132
|
+
style: {
|
|
133
|
+
fill: "#fff",
|
|
134
|
+
fontSize: 12,
|
|
135
|
+
fontFamily: "Arial",
|
|
136
|
+
fontWeight: "bold",
|
|
137
|
+
padding: [2, 6],
|
|
138
|
+
boxStyle: { fill: "#00000099", cornerRadius: 6 },
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## 参数总览(表格)
|
|
145
|
+
|
|
146
|
+
> 这一节把所有入参集中在一个地方,方便快速查阅(字段名使用“点号路径”表示嵌套结构)。
|
|
147
|
+
|
|
148
|
+
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
|
149
|
+
| --- | --- | --- | --- | --- |
|
|
150
|
+
| `from` | `IUI` | 是 | - | 起点节点 |
|
|
151
|
+
| `to` | `IUI` | 是 | - | 终点节点 |
|
|
152
|
+
| `routeType` | `"orthogonal" \| "bezier" \| "straight" \| "custom"` | 否 | `"orthogonal"` | 路由类型 |
|
|
153
|
+
| `padding` | `number` | 否 | `20` | 出线段长度(从 linkPoint 沿法线外扩) |
|
|
154
|
+
| `margin` | `number` | 否 | `0` | 连接点与节点边界间距(让线不贴边) |
|
|
155
|
+
| `cornerRadius` | `number` | 否 | `16` | 正交/智能路由的圆角半径 |
|
|
156
|
+
| `opt1` | `TargetOption` | 否 | - | 起点单端端点策略(覆盖全局) |
|
|
157
|
+
| `opt2` | `TargetOption` | 否 | - | 终点单端端点策略(覆盖全局) |
|
|
158
|
+
| `bezierCurvature` | `number` | 否 | `0.6` | bezier 曲率/张力(越大越“张开”) |
|
|
159
|
+
| `routeOptions` | `{ ... }` | 否 | - | smart-route 参数(会做深合并,未传字段会用默认值) |
|
|
160
|
+
| `routeOptions.avoidPadding` | `number` | 否 | `margin` | 避障 padding:将需要避开的 bounds 外扩多少(local) |
|
|
161
|
+
| `routeOptions.intersectionPenalty` | `number` | 否 | `1e6` | 线段与避障矩形相交的惩罚分(越大越“绕开”) |
|
|
162
|
+
| `routeOptions.longStraightRatio` | `number` | 否 | `0.65` | 长直线惩罚阈值(maxSegment/total > ratio 开始惩罚) |
|
|
163
|
+
| `routeOptions.longStraightWeight` | `number` | 否 | `2000` | 长直线惩罚权重 |
|
|
164
|
+
| `routeOptions.enableSRoutes` | `boolean` | 否 | `true` | 是否生成 S-route(两次转折)候选 |
|
|
165
|
+
| `routeOptions.bezierFallbackDistance` | `number` | 否 | `0` | bezier 近距离降级阈值(小于该值或节点重叠可降级为正交圆角) |
|
|
166
|
+
| `onDraw` | `({ s, e, defaultResult }) => Partial<{ points; path }> \| void` | 否 | - | 自定义绘制(入参/出参 points/path 都是 world 坐标) |
|
|
167
|
+
| `updateMode` | `"event" \| "render" \| "manual"` | 否 | `"event"` | 自动更新模式(协同场景建议用 render) |
|
|
168
|
+
| `renderThrottleMs` | `number` | 否 | `16` | render 模式节流(ms) |
|
|
169
|
+
| `getNodeId` | `(node: IUI) => string` | 否 | - | 协同序列化:node -> id(用于 getState/onChange) |
|
|
170
|
+
| `onChange` | `({ reason, prev, next, diff, changedKeys }) => void` | 否 | - | 统一变更回调(reason: `"label" \| "setState"`) |
|
|
171
|
+
| `onLabelChange` | `({ oldText, newText }) => void` | 否 | - | label 文本变化回调 |
|
|
172
|
+
| `stroke` | `string` | 否 | `"#ffffff"` | 线条颜色 |
|
|
173
|
+
| `strokeWidth` | `number` | 否 | `2` | 线宽 |
|
|
174
|
+
| `dashPattern` | `number[]` | 否 | - | 虚线,例如 `[6, 4]` |
|
|
175
|
+
| `startArrow` | `IArrowStyle` | 否 | - | 起点箭头样式 |
|
|
176
|
+
| `endArrow` | `IArrowStyle` | 否 | `"triangle"` | 终点箭头样式 |
|
|
177
|
+
| `scaleMode` | `"world" \| "pixel"` | 否 | `"world"` | 缩放策略(pixel:线宽/箭头保持像素大小) |
|
|
178
|
+
| `arrowBaseScale` | `number` | 否 | `1` | 箭头基准缩放(配合 pixel 更常用) |
|
|
179
|
+
| `label` | `{ ... }` | 否 | - | 连线文字配置(存在时可显示/编辑) |
|
|
180
|
+
| `label.text` | `string` | 否 | - | 初始文字(空/空白会被视为不创建 label) |
|
|
181
|
+
| `label.editable` | `boolean` | 否 | - | 是否允许编辑(打开 inner editor) |
|
|
182
|
+
| `label.style` | `Partial<ITextInputData>` | 否 | - | 文案样式(fill/fontSize/boxStyle/padding 等) |
|
|
183
|
+
| `labelOnDoubleClick` | `boolean` | 否 | `true` | 是否允许双击连线打开/创建 label |
|
|
184
|
+
|
|
185
|
+
### `TargetOption`(用于 `opt1/opt2`)表格
|
|
186
|
+
|
|
187
|
+
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
|
188
|
+
| --- | --- | --- | --- | --- |
|
|
189
|
+
| `optX.side` | `"top" \| "right" \| "bottom" \| "left" \| "auto"` | 否 | `"auto"` | 固定连接面,或自动择优 |
|
|
190
|
+
| `optX.percent` | `number` | 否 | `0.5` | 连接点在该面的比例(0~1,0.5=边中点) |
|
|
191
|
+
| `optX.padding` | `number` | 否 | - | 单端 padding(覆盖全局 padding) |
|
|
192
|
+
| `optX.margin` | `number` | 否 | - | 单端 margin(覆盖全局 margin) |
|
|
193
|
+
| `optX.linkPoint` | `IPointData` | 否 | - | 固定连接点(world,优先级最高) |
|
|
194
|
+
|
|
195
|
+
### 必填
|
|
196
|
+
|
|
197
|
+
- `from: IUI`:起点节点
|
|
198
|
+
- `to: IUI`:终点节点
|
|
199
|
+
|
|
200
|
+
### 端点与路由
|
|
201
|
+
|
|
202
|
+
- `routeType?: "orthogonal" | "bezier" | "straight" | "custom"`
|
|
203
|
+
- `"orthogonal"`:正交折线 + 圆角(smart-route)
|
|
204
|
+
- `"bezier"`:smooth-step 风格曲线(在节点很近/重叠时可选降级为正交)
|
|
205
|
+
- `"straight"`:直线(仍会包含 linkPoint/paddingPoint 的出线段)
|
|
206
|
+
- `"custom"`:默认给一个可用结果,但你应通过 `onDraw` 覆盖
|
|
207
|
+
- `padding?: number`:出线段长度(从 linkPoint 沿法线外扩)
|
|
208
|
+
- `margin?: number`:连接点与节点边界的间距(让线不要贴边)
|
|
209
|
+
- `cornerRadius?: number`:正交圆角半径
|
|
210
|
+
- `opt1?: TargetOption` / `opt2?: TargetOption`:单端覆盖(见下方 TargetOption)
|
|
211
|
+
|
|
212
|
+
### Bezier
|
|
213
|
+

|
|
214
|
+
|
|
215
|
+
- `bezierCurvature?: number`:曲率/张力(越大曲线“张开”越明显)
|
|
216
|
+
- `routeOptions?.bezierFallbackDistance?: number`:当 `routeType="bezier"` 时,若两端 padding 点距离小于该值(或节点重叠),可降级为正交圆角
|
|
217
|
+
- 默认 `0`:尽量保持贝塞尔
|
|
218
|
+
- 推荐 `140`:近距离更稳定、避免回勾
|
|
219
|
+
|
|
220
|
+
### 样式
|
|
221
|
+
|
|
222
|
+
- `stroke?: string`
|
|
223
|
+
- `strokeWidth?: number`
|
|
224
|
+
- `dashPattern?: number[]`:虚线,例如 `[6, 4]`
|
|
225
|
+
- `startArrow?: IArrowStyle`
|
|
226
|
+
- `endArrow?: IArrowStyle`(默认 `"triangle"`)
|
|
227
|
+
|
|
228
|
+
### 缩放策略
|
|
229
|
+
|
|
230
|
+
- `scaleMode?: "world" | "pixel"`
|
|
231
|
+
- `"world"`:跟随画布缩放(默认)
|
|
232
|
+
- `"pixel"`:保持像素大小(线宽/箭头不随 zoom 变化)
|
|
233
|
+
- `arrowBaseScale?: number`:箭头基准缩放(配合 pixel 模式更常用)
|
|
234
|
+
|
|
235
|
+
### label(连线文字)
|
|
236
|
+
|
|
237
|
+
- `label?: { text?: string; editable?: boolean; style?: Partial<ITextInputData> }`
|
|
238
|
+
- `labelOnDoubleClick?: boolean`:是否允许双击连线打开/创建 label(默认 true)
|
|
239
|
+
|
|
240
|
+
> 提示:如果你不传 `style.boxStyle/padding`,组件会给 label 自动加半透明背景遮挡线条,保证可读。
|
|
241
|
+
|
|
242
|
+
### 更新模式(协同/性能)
|
|
243
|
+
|
|
244
|
+
- `updateMode?: "event" | "render" | "manual"`
|
|
245
|
+
- `event`:仅交互事件触发 `update()`(性能最好,默认)
|
|
246
|
+
- `render`:每帧 `RenderEvent.END` 触发(适合协同/程序改变坐标)
|
|
247
|
+
- `manual`:完全手动
|
|
248
|
+
- `renderThrottleMs?: number`:`render` 模式节流,推荐 `16~33`
|
|
249
|
+
|
|
250
|
+
### 协同同步
|
|
251
|
+
|
|
252
|
+
- `getNodeId?: (node: IUI) => string`:用于 `getState`
|
|
253
|
+
- `onChange?: ({ reason, prev, next, diff, changedKeys }) => void`:结构变化统一回调(用于写入 Yjs diff)
|
|
254
|
+
- `onLabelChange?: ({ oldText, newText }) => void`:label 文本变化
|
|
255
|
+
|
|
256
|
+
## TargetOption(单端端点策略)
|
|
257
|
+
|
|
258
|
+
`opt1/opt2` 的字段与优先级(从高到低):
|
|
259
|
+
|
|
260
|
+
1. `linkPoint?: IPointData`(world 坐标):固定连接点(最高优先级)
|
|
261
|
+
2. `side?: "top" | "right" | "bottom" | "left" | "auto"` + `percent?: number`:在某条边上按比例取点
|
|
262
|
+
|
|
263
|
+
其它:
|
|
264
|
+
|
|
265
|
+
- `padding?: number` / `margin?: number`:单端覆盖
|
|
266
|
+
- `percent` 默认 `0.5`(边中点)
|
|
267
|
+
|
|
268
|
+
## 协同:序列化/恢复(getState / setState)
|
|
269
|
+
|
|
270
|
+
你可以把 Connector 状态写入 Yjs(或其它 CRDT),并在远端恢复:
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
// 1) 序列化:需要提供 node -> id
|
|
274
|
+
const state = edge.getState((node) => String((node as any).id));
|
|
275
|
+
|
|
276
|
+
// 2) 恢复:需要提供 id -> node
|
|
277
|
+
edge.setState(state, (id) => nodeById.get(id));
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## 协同:onChange / onLabelChange
|
|
281
|
+
|
|
282
|
+
如果你希望 **label 变化** 能自动产出 “可同步的 diff”,可以用 `onChange`:
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
const edge = new Connector(app, {
|
|
286
|
+
from: a,
|
|
287
|
+
to: b,
|
|
288
|
+
getNodeId: (node) => String((node as any).id),
|
|
289
|
+
onChange: ({ reason, diff }) => {
|
|
290
|
+
// 把 diff 写入 Yjs
|
|
291
|
+
console.log(reason, diff);
|
|
292
|
+
},
|
|
293
|
+
onLabelChange: ({ oldText, newText }) => {
|
|
294
|
+
console.log(oldText, newText);
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
协同/性能注意事项:
|
|
300
|
+
|
|
301
|
+
- **diff 对比是稳定的**:内部对对象字段做 key 排序稳定序列化,避免误触发 `onChange`
|
|
302
|
+
- **避免重复绑定**:同一节点多次被设置为 `from/to` 时,内部会去重绑定拖拽监听
|
|
303
|
+
- **label 变更会自动合并**:输入过程中可能产生高频 `RenderEvent.END`,内部会合并到同一微任务批次再触发回调
|
|
304
|
+
|
|
305
|
+
## 性能与更新模式(updateMode)
|
|
306
|
+
|
|
307
|
+
- `event`(默认):仅拖拽/交互触发 `update()`,性能最好
|
|
308
|
+
- `render`:每帧 `RenderEvent.END` 强制 `update()`,适合协同/程序频繁更新坐标
|
|
309
|
+
- `manual`:你自己控制刷新(可调用 `connector.invalidate()` 或 `connector.update()`)
|
|
310
|
+
|
|
311
|
+
### render 模式节流
|
|
312
|
+
|
|
313
|
+
协同场景建议开启节流减少压力:
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
const edge = new Connector(app, {
|
|
317
|
+
from: a,
|
|
318
|
+
to: b,
|
|
319
|
+
updateMode: "render",
|
|
320
|
+
renderThrottleMs: 16,
|
|
321
|
+
});
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## routeOptions(smart-route 参数)
|
|
325
|
+
|
|
326
|
+
你可以用 `routeOptions` 调整正交 smart-route 的取舍(更偏好绕开/更偏好 S-route 等):
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
const edge = new Connector(app, {
|
|
330
|
+
from: a,
|
|
331
|
+
to: b,
|
|
332
|
+
routeType: "orthogonal",
|
|
333
|
+
routeOptions: {
|
|
334
|
+
avoidPadding: 12,
|
|
335
|
+
intersectionPenalty: 1e6,
|
|
336
|
+
longStraightRatio: 0.65,
|
|
337
|
+
longStraightWeight: 2000,
|
|
338
|
+
enableSRoutes: true,
|
|
339
|
+
},
|
|
340
|
+
});
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
> `bezierFallbackDistance` 仅在 `routeType="bezier"` 时生效。
|
|
344
|
+
|
|
345
|
+
## 常见问题(FAQ)
|
|
346
|
+
|
|
347
|
+
### 1) 为什么我设置了 bezier,看起来还是折线?
|
|
348
|
+
|
|
349
|
+
- 你可能没有设置 `routeType: "bezier"`(默认是 `"orthogonal"`)
|
|
350
|
+
- 或者你显式把 `routeOptions.bezierFallbackDistance` 设置成较大值(例如 140),导致近距离自动降级为正交圆角
|
|
351
|
+
|
|
352
|
+
### 2) 为什么平移画布后连线会“漂移”?
|
|
353
|
+
|
|
354
|
+
本组件内部会把路由计算与绘制统一在 **Connector 的 local 坐标**,并在 `onDraw` 回调里对外提供 world 坐标,已避免常见的坐标系漂移问题。
|
|
355
|
+
如果你在 `onDraw` 返回自定义 `path`,务必返回 **world 坐标 path**(组件会自动转回 local)。
|
|
356
|
+
|
|
357
|
+
## API 导出
|
|
358
|
+
|
|
359
|
+
- 导出:`Connector` 以及相关类型(见 `src/types.ts`)
|
|
360
|
+
|
|
361
|
+
## 构建与发布
|
|
362
|
+
|
|
363
|
+
本包默认输出 **双产物**:
|
|
364
|
+
|
|
365
|
+
- ESM:`dist/esm`
|
|
366
|
+
- CJS:`dist/cjs`(`.cjs` 后缀)
|
|
367
|
+
|
|
368
|
+
可选:Rollup 生产 bundle(更适合做体积检查/发布前 smoke test):
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
pnpm run bundle:rollup
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
产物会输出到 `dist/bundle/`(含 `*.min.*`)。
|
|
375
|
+
|
|
376
|
+
发布前:
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
pnpm run build
|
|
380
|
+
npm publish
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## 备注
|
|
384
|
+
|
|
385
|
+
- 本包是 **ESM**(`type: module`),发布时会输出到 `dist/`(含类型声明)
|
|
386
|
+
- `leafer-editor` 作为 peerDependency,需要由业务侧安装与锁定版本
|