@lionad/leader-line
v1.0.0-alpha.0
Published
Draw a leader line in your web page.
Maintainers
Readme
@lionad/leader-line
在网页元素之间绘制引导线(SVG)。这是 anseki/leader-line 的现代维护版:构建于 Vite 8 + TypeScript 7 工具链,提供类型定义与读写分离的渲染调度。
Source Project: https://anseki.github.io/leader-line/
安装
pnpm add @lionad/leader-line// ESM
import LeaderLine from '@lionad/leader-line';
// CommonJS
const LeaderLine = require('@lionad/leader-line');<!-- <script> 标签(全局 LeaderLine) -->
<script src="https://unpkg.com/@lionad/leader-line/dist/leader-line.min.js"></script>const line = new LeaderLine(
document.getElementById('start'),
document.getElementById('end'),
{ color: 'coral', endPlug: 'arrow2' }
);Vue / Nuxt 集成
命令式 API 的声明式封装,两个平行子包:@lionad/leader-line-vue(composable + 组件)与 @lionad/leader-line-nuxt(Nuxt 模块)。
pnpm add @lionad/leader-line @lionad/leader-line-vue # Vue 3
pnpm add @lionad/leader-line-nuxt # Nuxt 4(含 vue 包)Vue:单线(options 深度响应)
<script setup>
import { ref, useTemplateRef } from 'vue';
import { useLeaderLine } from '@lionad/leader-line-vue';
const a = useTemplateRef('a');
const b = useTemplateRef('b');
const color = ref('coral');
// 锚点支持 Element / 模板 ref / selector / 组件实例;
// options 字段可为 ref——color.value = 'red' 即自动 setOptions(不重建)
const { line, position, show, hide, remove } = useLeaderLine(a, b, {
color,
endPlug: 'arrow2'
});
// 组件卸载自动 remove,无需手动清理
</script>Vue:批量连线(keyed diff)
import { useLeaderLines } from '@lionad/leader-line-vue';
const edges = ref([
{ key: 'a→b', start: elA, end: elB, color: 'coral', data: { fieldId: 'x' } }
]);
const { lines, getLine, findWhere, removeWhere } = useLeaderLines(edges, {
preventSame: true // 同 (start, end) 锚点对去重
});
// push → 新增;splice → 移除;同 key 改属性 → 就地更新;重排 → 零重建
removeWhere(e => e.data.fieldId === 'x'); // 谓词查询逃逸舱Vue:拖拽建连
import { useDragConnect } from '@lionad/leader-line-vue';
const { isDragging, startConnect } = useDragConnect({
validTarget: '.field-node', // selector 或谓词
preventSame: true,
onConnect: async (from, toEl, data) => { // 异步门禁,返回 false 拦截
return typeCheck(from, toEl);
}
});
// 模板:@mousedown="startConnect($event, elRef, { fieldId })"Vue:<LeaderLine> 组件糖
<LeaderLine :start="a" :end="b" color="coral" end-plug="arrow2" :dash="true" />
<!-- v-for 场景直接配合 :key 使用 -->Nuxt:零配置模块
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@lionad/leader-line-nuxt'],
leaderLine: {
defaults: { color: '#4a9eff', size: 2 } // 全局默认 options(需可 JSON 序列化)
}
});
// 之后全部 composable 与 <LeaderLine> 组件免 import 直接使用;
// 默认值合并优先级:调用处 > 模块默认 > 库默认。SSR 安全(client-only)锚点工厂也有托管封装(usePointAnchor / useAreaAnchor / useMouseHoverAnchor / useCaptionLabel / usePathLabel),scope 销毁时自动 remove(),杜绝 attachment 泄漏。
相比上游的新增
功能
- default exports(ESM 默认导出)
options.svgContainer—— 指定 SVG 挂载容器,默认document.body- 完整类型定义(
index.d.ts,覆盖公开 API 与 fork 特性) - 三产物:ESM(
dist/leader-line.mjs)、CommonJS(dist/leader-line.cjs)、IIFE(dist/leader-line.min.js)+ sourcemap
性能:requestPosition() 与 deferPositionUpdate
逐条调用 position() 更新 N 条线时,每条线的"布局读 + DOM 写"交替会触发 N 次强制同步 reflow。本包的渲染调度内核把一帧内的更新合并为"全部读 → 全部写",reflow 由 N 次降为至多 1 次(CDP LayoutCount 实测 50 → 1):
// 方式 A:逐调用调度(拖拽等高频场景推荐)
lines.forEach(line => line.requestPosition());
// 方式 B:全局开关,position() 自动走调度
LeaderLine.deferPositionUpdate = true;
lines.forEach(line => line.position());position() 默认保持同步语义(完全向后兼容);LeaderLine.positionByWindowResize 内部已走调度。
调度器已知限制:绑在模块窗口的 rAF 上,popup 独立窗口中的线按主窗口帧时钟 flush(主窗口隐藏时暂停);后台标签页的更新在恢复可见时一次性 flush。
修复
aplStats.position_plugOverheadSEis not defined@micro-zoe/micro-app中的getFrame error
从 leader-line(旧包)迁移
@lionad/[email protected] 是新包名下的首个版本,等价于旧 fork(本仓库 [email protected] 系列)的继续:
- "leader-line": "^1.1.0"
+ "@lionad/leader-line": "^1.0.0"- IE11 与旧 Edge 不再支持(构建目标为现代浏览器)
- 产物路径变更:
dist/下三格式(见上);旧根目录三文件(leader-line.js/leader-line.min.js/leader-line.esm.js)不再提供 - Bower 渠道已移除(Bower 已 EOL)
- API 完全兼容;
requestPosition()/deferPositionUpdate为纯新增
开发
pnpm install
pnpm dev # vite build --watch(development,保留 [DEBUG])
pnpm build # production 三产物 → dist/
pnpm test # vitest:unit(node)+ browser(playwright chromium)
pnpm dev:playground # Nuxt playground(场景 demo + bench,LAN 可访问)
pnpm lint # eslint 9 flat
pnpm typecheck # tsgo(库)+ nuxi typecheck(playground)
pnpm test:smoke # 产物 <script> 直载冒烟
pnpm test:bench # 渲染管线基准(CDP LayoutCount,需 vite dev server)