Linker 元素
Linker —— 高性能 Canvas 连线元素。
更新日志
当前版本为 v1.0.0-beta.3,查看更新日志。
📦 安装插件(本地安装)
本插件不发布于公开 NPM 仓库,通过本地 .tgz 文件安装使用,需 购买插件 授权后才能使用。
第一步:获取插件包
购买后,你将获得一个名为 leafer-in-linker-1.0.0-beta.3.tgz 的安装包。
将该文件放置在你的项目根目录下的 leafer 文件夹中统一管理,安装后请勿删除。
第二步:本地安装命令
根据你使用的包管理器,选择以下方式之一:
sh
npm install ./leafer/leafer-in-linker-1.0.0-beta.3.tgzsh
pnpm add ./leafer/leafer-in-linker-1.0.0-beta.3.tgzsh
yarn add ./leafer/leafer-in-linker-1.0.0-beta.3.tgzsh
bun add ./leafer/leafer-in-linker-1.0.0-beta.3.tgz将在 package.json 中自动增加本地依赖:
"@leafer-in/linker": "file:leafer/leafer-in-linker-1.0.0-beta.3.tgz"
或通过 script 标签引入,使用全局变量 LeaferIN.linker 访问插件内部功能。
解压 leafer-in-linker-1.0.0-beta.3.tgz ,复制 package/dist/linker.js 使用。
html
<script src="/lib/leafer/linker.js"></script>
<script>
const { Linker, LinkerData } = LeaferIN.linker
</script>关键属性
startPoint: ILinkerPointData
连线的起点。
ts
interface ILinkerPointData {
id?: string | UI // 起点元素的 id,也支持元素实例(只是导出不了json)
direction?: IDirection4 | 'center' // 连线的方向(相对元素),为 center 时表示自动方向
point?: IAlign | IUnitPointData // 连接点(相对元素实际内容的box坐标点,支持使用对齐方向名、百分比坐标)
offset?: IOptionPointData // 相对连接点的偏移值
}
type IDirection4 = 'top' | 'right' | 'bottom' | 'left'
type IAlign =
| 'top-left'
| 'top'
| 'top-right'
| 'right'
| 'bottom-right'
| 'bottom'
| 'bottom-left'
| 'left'
| 'center'
interface IUnitPointData extends IPointData {
type?: 'percent' | 'px'
}
interface IPointData {
x: number
y: number
}
interface IOptionPointData {
x?: number
y?: number
}endPoint: ILinkerPointData
连线的终点。
计算属性(只读)
只有当连线元素首次布局后,以下属性才有值。
startNode: UI
连线起点的元素实例。
endNode: UI
连线终点的元素实例。
startData: ILinkerComputedPointData
连线起点的计算数据。
ts
interface ILinkerComputedPointData {
auto: boolean // 是否自动连线方向
direction: IAlign // 当前实际的连线方向 (相对元素)
point: IPointData // 当前实际连接点的坐标 (相对元素实际内容的box坐标系)
}endData: ILinkerComputedPointData
连线终点的计算数据。
被连线元素上增加的属性
startLinker?: Linker[]
以当前元素作为起点的所有连线实例。
endLinker?: Linker[]
以当前元素作为终点的所有连线实例。
关键方法
createStartPoint ( worldPoint: IPointData, node?: UI, options?: ILinkerPointOptions ): ILinkerPointData
创建连线的起点 startPoint。
根据事件中的 world 世界坐标点,自动获取在 node 目标元素上的连接点数据进行创建。
node 参数不存在时将创建纯坐标点。
ts
interface IPointData {
x: number
y: number
}
interface ILinkerPointOptions {
snapRadius?: number // 吸附到方向点上之后,如果吸附距离超过这个吸附半径(相对元素的Box坐标系),连接点对象会自动增加 offset: {x,y}
}createEndPoint ( worldPoint: IPointData, node?: UI, options?: ILinkerPointOptions ): ILinkerPointData
创建连线的终点 endPoint。
createLinkerPoint ( worldPoint: IPointData, node?: UI, options?: ILinkerPointOptions ): ILinkerPointData
仅生成连接点,可以自己修改数据后,再设置到连线的 startPoint、endPoint 上。
示例
创建连线元素
ts
// #Linker [创建连线元素]
import { App, Box, Ellipse } from 'leafer-ui'
import '@leafer-in/editor' // 导入图形编辑器插件
import '@leafer-in/viewport' // 导入视口插件 (可选)
import '@leafer-in/find' // 导入查找元素插件
import '@leafer-in/arrow' // 导入箭头插件
import { Linker } from '@leafer-in/linker' // 导入连线插件
const app = new App({ view: window, editor: {} })
app.tree.cacheId = true // 创建时缓存元素id, 加快查找id的速度
const rect1 = Box.one({ id: 'rect1', editable: true, fill: '#FEB027', cornerRadius: [20, 0, 0, 20], children: [new Ellipse({ x: 92, y: 50, width: 8, height: 8, around: 'center', fill: '#836DFF', stroke: '#000', strokeWidth: 1 })] }, 100, 200, 100, 100)
const rect3 = Box.one({ id: 'rect2', editable: true, fill: '#FFE04B', cornerRadius: [0, 20, 20, 0], children: [new Ellipse({ x: 8, y: 20, width: 8, height: 8, around: 'center', fill: '#836DFF' })] }, 400, 100, 100, 100)
const rect2 = Box.one({ id: 'rect3', editable: true, fill: '#FFE04B', cornerRadius: [0, 20, 20, 0] }, 400, 300)
const linker1 = new Linker({ // 类似 AI 工作流连线,位于底部
stroke: [{ type: 'solid', color: '#000', style: { strokeWidth: 4 } }, { type: 'solid', color: '#836DFF' }],
strokeWidth: 2,
startPoint: { id: 'rect1', point: 'right' },
endPoint: { id: 'rect2', direction: 'left', point: 'top-left', offset: { y: 20 } },
})
app.tree.add(linker1)
app.tree.add(rect1)
app.tree.add(rect2)
app.tree.add(rect3)
const linker2 = new Linker({ // 带箭头的连线,位于顶部
stroke: '#ff4c4c',
strokeWidth: 2,
startPoint: { id: 'rect1' }, // 箭头自动方向
endPoint: { id: 'rect3' },
endArrow: 'angle'
})
app.tree.add(linker2)连线元素固定线宽不随视图放大
ts
// #Linker [连线元素固定线宽不随视图放大]
import { App, Rect } from 'leafer-ui'
import '@leafer-in/editor' // 导入图形编辑器插件
import '@leafer-in/viewport' // 导入视口插件 (可选)
import '@leafer-in/find' // 导入查找元素插件
import '@leafer-in/arrow' // 导入箭头插件
import { Linker } from '@leafer-in/linker' // 导入连线插件
const app = new App({ view: window, editor: {} })
app.tree.cacheId = true // 创建时缓存元素id, 加快查找id的速度
const rect1 = Rect.one({ id: 'rect1', editable: true, fill: '#FEB027', cornerRadius: [20, 0, 0, 20] }, 100, 100)
const rect2 = Rect.one({ id: 'rect2', editable: true, fill: '#FFE04B', cornerRadius: [0, 20, 20, 0] }, 300, 100)
app.tree.add(rect1)
app.tree.add(rect2)
const linker = new Linker({
stroke: '#836DFF',
strokeWidth: 2,
strokeScaleFixed: 'zoom-in', // 固定线宽,不随视图放大
startPoint: { id: 'rect1' },
endPoint: { id: 'rect2' },
endArrow: 'angle'
})
app.tree.add(linker)创建连线点,自动吸附方向、偏移距离
ts
// #Linker [创建连线点,自动吸附方向、偏移距离]
import { App, Rect } from 'leafer-ui'
import '@leafer-in/editor' // 导入图形编辑器插件
import '@leafer-in/viewport' // 导入视口插件 (可选)
import '@leafer-in/find' // 导入查找元素插件
import '@leafer-in/arrow' // 导入箭头插件
import { Linker } from '@leafer-in/linker' // 导入连线插件
const app = new App({ view: window, editor: {} })
app.tree.cacheId = true // 创建时缓存元素id, 加快查找id的速度
const rect1 = Rect.one({ id: 'rect1', editable: true, fill: '#FEB027', cornerRadius: [20, 0, 0, 20] }, 100, 100)
const rect2 = Rect.one({ id: 'rect2', editable: true, fill: '#FFE04B', cornerRadius: [0, 20, 20, 0] }, 300, 100)
const rect3 = Rect.one({ id: 'rect3', editable: true, fill: '#FFE04B', cornerRadius: [0, 20, 20, 0] }, 300, 300)
app.tree.add(rect1)
app.tree.add(rect2)
app.tree.add(rect3)
const linker = new Linker({
stroke: '#836DFF',
strokeWidth: 2,
startPoint: { id: 'rect1' },
endPoint: { id: 'rect2' },
endArrow: 'arrow'
})
app.tree.add(linker)
console.log(linker.createStartPoint({ x: 400, y: 380 }, rect3, { // 创建连线点,自动吸附方向
snapRadius: 10 // 吸附到方向点上之后,如果吸附距离超过这个吸附半径(相对元素的Box坐标系),连接点对象会自动增加 offset: {x,y}
}))