topo-engine
topo-engine
配电台区(低压配电网)单线图拓扑成图引擎,基于 Vue 3 + AntV G6 v5。
输入一份台区拓扑 JSON,自动完成「解析 → 建树找根 → 横平竖直、0 交叉 的正交布局 → 深色 SCADA 风格渲染」,并提供开箱即用的 Vue 组件与一整套拓扑查询 / 样式 / 动画 / 标注控制 API。
功能特性
- 🧩 Vue 3 组件 —
TopoGraph(画布;可选左上工具条默认隐藏,:toolbar开启)、SidePanel(设备详情与上下游)、DistanceTop10(父子连线距离 Top10 面板) - 🎨 深色 / 浅色双主题 — 黑底 SCADA 或白底两种画布风格,图元 / 导线 / 文字随之配套适配,可随时切换(
themeprop 或工具栏按钮)。默认浅色主题 - 🗺 图例 — 可选图例面板(
legendprop,默认关闭):按当前图实际设备类别自动生成、颜色随主题,支持legendItems自定义项与点击折叠 - 📐 自研正交布局 — 主干沿最长路径横向铺开 + 分支带垂直直走,整图横平竖直、0 交叉、0 重叠,边缘路由为直线 / L 形折线
- 🏢 站房/公配室多母线 — 站内含多条母线时母线并排(同一水平线);母联开关经「半矩形(⊔)」走线连接两母线(母线端向下 → 水平 → 母联开关 → 水平 → 向上),母联短名为「母联」并居中显示在 ⊔ 内部;其余开关各挂各自母线;单母线站房行为不变
- 🔍 拓扑查询 API — 节点 / 边 / 邻居 / 子树 / 主干链 / 路径 / 坐标 查询
- 🎨 样式控制 — 节点、边样式覆盖与批量重置
- 🎨 节点 / 电表染色 — 按 psrId(设备编码) 染普通节点、按 assetNo(资产编号) 染计量箱内电表户(状态色、告警色场景)
- ✨ 动画与高亮 — 节点脉动、节点光晕(发光环,颜色可设)、边流动、路径高亮、其余变暗、异常标注
- 📝 文字标注 — 附加文字、用户名 full / short / hidden 切换
- 🃏 卡片盒 — 节点信息卡片(字段 + 按钮),适配"运行曲线/工单跳转"类场景
- 🔗 连接线 / 拓扑线 — 任意两节点动态连接线、路径拓扑高亮线
- 🎧 事件系统 — 点击 / 悬停 / 画布空白 / 视口变化事件总线
- 💾 导出 — 整图 PNG 下载、DataURL、图数据 JSON
- 📦 零配置渲染 — 组件内置主题与解析渲染,
data或dataUrl二选一即可出图
安装
npm install topo-engine
# 或 yarn add topo-engine / pnpm add topo-engine
- 环境要求:Vue 3.4+(peerDependency);
@antv/g6v5 已作为依赖随包安装,无需手动配置。 - 组件深色样式不自动注入,使用时需引入样式文件:
import 'topo-engine/style.css';
📖 完整 API 参考手册随包发布:安装后可打开
node_modules/topo-engine/docs/API.md, 或在线查看仓库中的 docs/API.md(事件、卡片、连接线、布局参数、TS 类型等一应俱全)。
快速开始
1. 最小示例 —— 只画一张图
<script setup>
import { ref } from 'vue';
import { TopoGraph } from 'topo-engine';
import 'topo-engine/style.css';
// 两种数据来源任选其一:
// - dataUrl:内部用 fetch 加载(注意放 public/ 下或跨域可达)
// - data :直接传入解析好的 JSON 对象(优先级高于 dataUrl)
const dataUrl = ref('/data/topology.json');
const onLoaded = ({ title, stats }) => {
console.log('加载完成', title, stats); // { total, depth, leaves, byCat }
};
</script>
<template>
<!-- 组件撑满父容器,父容器必须有明确高度 -->
<div class="page">
<TopoGraph :data-url="dataUrl" @loaded="onLoaded" />
</div>
</template>
<style scoped>
.page { height: 640px; }
</style>
2. 组合示例 —— 图 + 详情面板 + Top10 距离面板
<script setup>
import { ref } from 'vue';
import { TopoGraph, SidePanel, DistanceTop10 } from 'topo-engine';
import 'topo-engine/style.css';
const topo = ref(null); // ref → 调用完整控制 API
const graphData = ref(null); // 直接传数据对象
const panelOpen = ref(false);
const selected = ref(null);
const upstream = ref([]);
const downstream = ref([]);
const stats = ref({});
const distances = ref([]);
function onSelect({ node, upstream: up, downstream: down }) {
selected.value = node;
upstream.value = up;
downstream.value = down;
panelOpen.value = true;
}
function onTopDistances(list) { distances.value = list; }
function jumpTo(id) { topo.value?.selectNode(id); }
</script>
<template>
<div class="app">
<div class="graph-area">
<TopoGraph
ref="topo"
:data="graphData"
@node-select="onSelect"
@top-distances="onTopDistances"
/>
<SidePanel
v-if="panelOpen"
:node="selected"
:upstream="upstream"
:downstream="downstream"
:stats="stats"
@close="panelOpen = false"
@jump="jumpTo"
/>
</div>
<DistanceTop10
v-if="distances.length"
:distances="distances"
@close="distances = []"
@jump="jumpTo"
/>
</div>
</template>
<style scoped>
.app { display: flex; height: 720px; }
.graph-area { flex: 1; display: flex; min-width: 0; position: relative; }
</style>
3. 只用布局 / 解析工具函数(不依赖组件)
import { parseTopo, computeOrthogonalLayout, buildGraphData } from 'topo-engine';
const model = parseTopo(rawJson); // 原始 JSON → 图模型(含 nodes/edges/rootId/stats)
const layout = computeOrthogonalLayout(model); // 正交布局结果(节点坐标 + 每边折线点序列)
const g6Data = buildGraphData(model, layout); // → G6 可直接消费的 { nodes, edges }
说明:包内渲染使用的自定义图元节点(
svg-symbol)与正交折线边(orth-polyline)目前仅在TopoGraph内部注册使用,未作为公开 API 导出。直接用 G6 手工拼图时建议以TopoGraph组件(或它的 render 流程)为基准,保证节点与边风格一致。
输入数据格式
顶层可以是 { code, msg, data: { nodes, relationships, stations } }(常见接口包装格式),也可以是直接 { nodes, relationships, stations } —— 引擎两种都接受。
{
"data": {
"nodes": [
{ "id": 1, "name": "1#台区.", "psrType": "0302", "symbolId": "1664029", "status": "0" },
{ "id": 2, "name": "1#台区低压熔丝.", "psrType": "3301", "symbolId": "68688", "status": "0" }
],
"relationships": [ { "from": 1, "to": 2 } ],
"stations": [
{ "id": 1, "name": "1#台区.", "contain": ["8ff4786d548a7073a2517297e801518ff456732f4d"] }
]
}
}
| 字段 | 说明 |
|---|---|
nodes[] |
设备/线路节点:id、name(可带结尾 .,渲染时会去掉)、psrType(图元类型码)、symbolId、psrId、status("0" 视为正常) |
relationships[] |
有向边 { from, to },方向为 电源 → 负荷;自动防环(BFS),入度为 0 者作为根,优先选变压器/开关 |
stations[] |
台区/站房:name 作为画布标题,contain 内为箱内设备的 psrId 列表 |
parseTopo 后模型节点会附带派生抽像字段:cat、catLabel、shortName、isLine、insideStation、isFuse 等(完整类型见 dist/index.d.ts)。
主要 psrType → 图元类别:
| psrType | 类别 | 渲染 |
|---|---|---|
0302 / 0110 |
配电变压器(柱上变) | 橙色圆 + 红圈 |
3301 / 321500000 |
开关 / 熔丝 | 红色矩形(开关名自动缩写为 K 编号) |
3303 |
低压母线 | 白色短粗线(无文字标签) |
3202 / 320300000 |
电缆终端头 / 分接点 | 三角 / 红色米字(无文字标签) |
310100000 / 3201 / 3102 / 3101 |
低压导线(含电杆/导线分段) | 青色连接点(名称缩写为杆号区间) |
3112 / 31120003 |
计量箱 | 黑底白框 "JX"(有客户数据时显示为电能表图标 + 用户名) |
3218000 |
用户接入点 | 白圈 "J"(名称缩写为户号) |
32500000 |
低压配电箱(台区) | 站房 |
TopoGraph 组件参考
Props
| Prop | 类型 | 默认 | 说明 |
|---|---|---|---|
dataUrl |
String |
'' |
拓扑 JSON 的 URL(内部 fetch 加载)。变化后自动重新加载 |
data |
Object |
null |
直接传入 JSON 对象;优先级高于 dataUrl;深度 watch,变化自动重绘 |
customerData |
Array |
null |
客户数据([{ psrId, consumerList }]),注入计量箱并按户渲染 / 可点 |
theme |
'dark' | 'light' |
'light' |
画布主题:dark(黑底 SCADA)/ light(白底,图元配套加深,默认)。支持 v-model:theme,也可点内置工具栏 ☀️/🌙 按钮切换 |
toolbar |
Boolean |
false |
是否显示左上工具条(标题 / 统计 / 主题 / 图例 / 适应画布 / 导出 PNG),默认隐藏 |
legend |
Boolean |
false |
是否显示右下角图例面板,默认否。支持 v-model:legend(开启 toolbar 后工具条内有 🗺 图例按钮)。图例按当前图实际出现的设备类别自动生成,颜色跟随主题;面板可点击标题折叠 |
legendItems |
Array |
null |
自定义图例项(覆盖自动生成):[{ label, shape, color?, text?, key? }]。shape 可选 transformer/switch/fuse/bus/cableTerminal/junction/meterBox/consumer/line/meterUser/station/edge 或通用 square/ring/triangle/hline/text/dot |
Emits
| 事件 | 载荷 | 触发时机 |
|---|---|---|
loaded |
{ title, stats },stats = { total, depth, leaves, byCat } |
每次数据渲染完成 |
node-select |
{ node, upstream, downstream }(均为解析后模型节点) |
点击节点(含金框选中与详情联动);空白清除时 node=null |
customer-select |
{ node, customer, index, count, upstream, downstream } |
点中计量箱内某个用户(展示客户档案) |
top-distances |
Array<{ parent: {id,name,catLabel}, child: {id,name,catLabel}, distance }>(≤10) |
渲染完成时,父-子连线折线长度 Top10(过滤站内边与主干鱼骨边) |
update:legend |
新布尔值 | 工具条 🗺 图例按钮点击(配合 v-model:legend) |
图例(legend)
<!-- 默认不显示;开启即用(按图内容自动生成条目,颜色随主题) -->
<TopoGraph :data-url="'/data/topo.json'" legend />
<!-- 自定义图例项 -->
<TopoGraph
:data-url="'/data/topo.json'"
:legend="true"
:legend-items="[
{ label: '正常设备', shape: 'square', color: '#22C55E' },
{ label: '告警设备', shape: 'ring', color: '#EF4444' },
{ label: '停电', shape: 'triangle', color: '#9CA3AF' },
{ label: 'JX', shape: 'text', color: '#3A3A3A', text: 'JX' },
]"
/>
自动图例内容:配电变压器 / 开关 / 熔丝 / 低压母线 / 电缆终端头 / 密母分接点 / 计量箱 / 用户接入点 / 低压导线点 / 低压配电箱 / 其它设备(仅显示图中存在的),末尾固定为 主干导线 / 分支导线,图中含计量箱客户数据时再追加 客户电表。
内置交互与 UI
- 滚轮缩放、拖拽平移、悬停高亮(上下游与连线),点击选中(金色虚框,再次点空白取消)。
- 计量箱用户点击:单户箱整箱即该户;多户箱点电表格 / 户名 = 该户客户档案(悬停青圈、选中金圈),点箱体空白 = 选中整箱(事件
consumer:click/customer-select)。 - 左上角工具条默认隐藏:传
:toolbar="true"后显示标题 /节点 n · 边 m · 深度 d · 叶子 l统计 / 🌙 主题 / 🗺 图例 /「适应画布」/「导出 PNG」按钮。 - 图例默认关闭:传
:legend="true"(或v-model:legend)后右下角出现图例面板,点击标题可折叠。 - 加载中 / 出错(如 dataUrl 404)有内置遮罩提示。
- 卸载时自动
destroy()图实例与事件监听,无内存泄漏。
通过 ref 调用的方法
<TopoGraph ref="topo"> 后,topo 暴露 TopoApi 的全部公开方法(下节 API 表),外加:
| 方法 | 说明 |
|---|---|
loadRaw(jsonText) |
用一段 JSON 文本(如本地文件上传内容)重新成图 |
selectNode(id) |
选中某节点并联动 node-select 事件 |
selectCustomer(nodeId, index) |
编程式选中计量箱内第 index 户(联动 customer-select) |
getSelectedCustomer() |
当前选中的户:{ nodeId, index, customer, node } | null |
resetView() |
适应画布 |
exportPng() |
导出整图 PNG(按画布标题命名下载) |
getLayoutData() |
获取当前正交布局数据(坐标 / 折线 / stats) |
getTopDistances() |
获取最近一次 Top10 距离结果 |
主题切换(深色 / 浅色)
引擎内置两套主题,浅色为默认(白底,图元配套深色,适合打印或嵌入浅色页面);深色为黑底 SCADA 风格。
TopoGraph::theme取值'light'(默认)或'dark',推荐v-model:theme双向绑定;开启:toolbar="true"后工具条内置 ☀️ / 🌙 切换按钮(点击 emitupdate:theme)。-SidePanel/DistanceTop10:同样接收themeprop,与画布保持一致观感。- 切换主题会按当前数据自动重建画布:G6 画布背景、图元、边、标注文字全部随主题更新,布局不变。
<script setup>
import { ref } from 'vue';
import { TopoGraph } from 'topo-engine';
import 'topo-engine/style.css';
const theme = ref('light'); // 初始浅色(默认),可在运行时切换
const dataUrl = ref('/data/topology.json');
</script>
<template>
<div class="page">
<TopoGraph v-model:theme="theme" :data-url="dataUrl" />
</div>
</template>
说明:主题色板定义在包内
theme.js(THEMES.dark/THEMES.light,已随库打包,未作为公开导出);若需要按自有品牌定制,可在外层自行覆盖dist/style.css中各组件的--tp-*/--sp-*/--dt-*CSS 变量。
控制 API(TopoApi 方法,经组件 ref 直接调用)
也可自行
import { TopoApi },按new TopoApi(graph, model, layout, nodeByIdMap)构造后调用同一套方法;事件与查询见下。使用组件时无需关心内部构造。
📌 引用统一(id / psrId / assetNo):所有目标入参(查询/定位/样式/高亮/动画/文字/卡片/连线…)都可传 节点内部 id、psrId(设备编码) 或 客户 assetNo(资产编号,兼容 consNo/consId):
- 命中普通节点 → 作用在该节点;
- 命中箱内电表户 → 视觉/定位/动画精确作用在该户表位(光环/高亮环/脉动/文字/染色/卡片), 查询/拓扑按所在计量箱参与(
getNode(assetNo)返回箱节点并附customer信息), 定位聚焦表位中心(locateNode(assetNo)、getNodePosition(assetNo))。topo.locateNode(assetNo); // 定位到某户表位中心 topo.highlightNode(assetNo, { color: '#FF0000' }); // 该户表位高亮环 topo.setNodeGlow(assetNo, { color: '#FF6600' }); // 该户表位光晕 topo.setNodeGlow(assetNo, { blink: true, color: '#FF6600' }); // 该户表位整体闪烁 topo.setNodePulse(assetNo); // 该户电表格脉动 topo.setText(assetNo, '异常'); // 表位上方标注 topo.showCard(assetNo); // 客户档案卡片(定位在表位旁) topo.selectNode(assetNo); // 编程选中该户(联动 customer-select) topo.getNode(assetNo); // → 所在箱节点副本 { …, customer, customerIndex, targetKind:'customer' } topo.resolveRef(assetNo); // → { kind:'customer', boxId, index, customer, … } | null
查询
| 方法 | 说明 |
|---|---|
getNode(nodeId) |
按 ID 取节点(解析后模型节点) |
getAllNodes() |
全部节点 |
findNodes(filter) |
多条件 AND 过滤,filter 支持 { cat, psrType, name, shortName, status, insideStation, … },值可为字符串 / 布尔 / RegExp |
getSelectedId() |
当前选中节点 ID |
getNeighbors(id) |
{ upstream: [], downstream: [] } |
getStreamNodes(id, 'upstream'|'downstream') |
沿流向 BFS 取节点链 |
getTrunkNodes() / getSubtreeNodes(id) |
主干链节点 / 子树节点 |
getPath(a, b) |
两节点间路径(不可达返回 null) |
getEdge(src, tgt) / getEdges() |
按端点取边 / 全部边 |
getStreamEdges(id, dir) / getMainEdge() |
沿流边的链 / 主干边 |
getNodePosition(id) / getEdgePath(src, tgt) / getGraphBounds() |
坐标 / 边折线点序列 / 全图包围盒 |
getStats() |
{ total, depth, leaves, byCat } |
视图
fitView(padding?)、zoomTo(ratio, center?)、zoomIn(step?)、zoomOut(step?)、locateNode(id, zoom?)、getViewport()
样式
setNodeStyle(id, style)、batchSetNodeStyle(ids, style)、resetNodeStyle(id)、resetAllNodeStyles()
setEdgeStyle(src, tgt, style)、batchSetEdgeStyle([[src,tgt],…], style)、resetEdgeStyle(src, tgt)
节点 / 箱内电表户染色(psrId / 资产编号)
// 普通节点:按 psrId(设备编码)整图单色换装(主体/引线/描边换成该色,白字细节保留)
topo.setNodeColor('8ff4786d548a7073a2517297e801518ff456732f4d', '#FF0000');
// 箱内电表户:按资产编号(assetNo,兼容 consNo/consId)染该户电表图标 + 户名
topo.setNodeColor('4230010007008084768', '#FF6600');
// 批量(数组 / 对象数组 / ref→color 对象均可)
topo.batchSetNodeColor({ '8ff4…': '#FF0000', '4230…': '#FF6600' });
// 清除 / 查询
topo.resetNodeColor('4230010007008084768');
topo.resetAllNodeColors();
topo.getNodeColor('4230010007008084768'); // → { kind, id, color } | null
引用规则与
addConnection一致:节点 id / psrId 命中普通节点;assetNo 命中计量箱内某户电表。 染色记录随主题切换 / 数据重渲染自动保留并重放(无需重新设置)。详见 docs/API.md。
高亮 / 变暗
topo.highlightNode('5', { color: '#FF0000', label: '异常', labelColor: '#FF0000' });
topo.unhighlightNode('5');
const path = topo.getPath('1', '5'); // 高亮一条供电路径
if (path) topo.highlightPath(path.map(n => n.id), { color: '#00FF00' });
topo.dimOthers(['1', '2'], 0.15); // 除指定节点外整体变暗
topo.unhighlightAll();
动画
topo.setNodePulse('2', { color: '#00C8FF', duration: 1500 }); // 节点脉动
topo.setNodeGlow('2', { color: '#FF0000' }); // 节点光晕(多层光环 + shadowBlur 辉光 + blur 面光底衬;ref 支持 psrId)
topo.setNodeGlow('2', { color: '#FF0000', intensity: 2, spread: 30, blink: true, duration: 800 }); // 更夸张:加强 + 更大扩散 + 图元整体闪烁
topo.removeNodeGlow('2');
topo.setEdgeFlow('1', '2', { color: '#00C8FF', duration: 2000 }); // 边流动
topo.removeAnimation('2');
topo.removeAllAnimations();
文字标注
setText(id, text, { color, fontSize })、removeText(id)、removeAllTexts()、setDeviceText(cat, fontSize)、changeUserName('full' | 'short' | 'hidden')
卡片盒
topo.showCard('5', {
title: '设备名称',
fields: [
{ label: '类型', value: '配电变压器' },
{ label: 'PSR编号', value: 'xxx' },
],
buttons: [{ text: '查看运行曲线', type: 'primary', onClick: () => console.log('click') }],
closable: true,
});
topo.hideCard('5');
topo.hideAllCards();
连接线 / 拓扑线
topo.addConnection('1', '8', { color: '#FF6600', width: 2, style: 'dashed' }); // 任意两节点连线
topo.removeAllConnections();
const lineId = topo.addTopoLine(['1', '3', '8'], { color: '#FF0000', width: 3 }); // 沿线路径画高亮线
topo.removeTopoLine(lineId);
topo.removeAllTopoLines();
事件总线(on / off)
| 事件 | 载荷 | 说明 |
|---|---|---|
node:click |
{ nodeId, node } |
节点点击 |
node:hover / node:unhover |
{ nodeId, node } / { nodeId } |
悬停进入 / 离开 |
edge:click |
{ edgeId, source, target } |
边点击 |
canvas:click |
{ event } |
画布空白处点击 |
viewport:change |
{ zoom, center } |
视口缩放 / 平移变化 |
card:button |
{ nodeId, buttonIndex } |
卡片按钮点击 |
consumer:click |
{ nodeId, index, customer, node } |
点中计量箱内用户(多户箱点格子;单户箱整箱即该户) |
const handler = ({ nodeId }) => console.log('点击了', nodeId);
topo.on('node:click', handler);
topo.off('node:click', handler); // 不传 handler 则移除该事件全部监听
导出 / 底层
exportPng(filename?)(整图下载)、toDataURL(opts?)、getGraphData()、getGraphInstance()(原始 G6 Graph)、getModel()、getLayoutData()、getNodeByIdMap()、update(graph, model, layout, map)、destroy()
文字渲染
- 设备标签自动换行:开关标签、站房标题、下方名称标签等文字根据设备宽度自动换行,避免文字重叠
- 站房标题自适应高度:站房框高度会根据标题换行行数自动扩展,确保多行标题完整显示在框内
- 母线 / 电缆终端头:不渲染额外文字标签(母线不显示"母线",电缆终端头不显示名称)
- 站房标题:使用独立属性
_stationTitle渲染,避免 G6 默认 label 重复绘制
计量箱客户数据
计量箱(psrType 3112)支持关联客户数据,渲染时根据客户数量自动切换显示模式:
| 模式 | 条件 | 渲染效果 |
|---|---|---|
| 无客户数据 | 未传入 customerData 或无匹配 | 原始 JX 黑底白字方框 |
| 单用户 | customerList 有 1 个用户 | 电能表图标(圆圈 + 竖线)+ 用户名;整箱即该户,点击即客户档案 |
| 多用户(显示名称) | customerList 2~20 个用户 | 方框内电能表网格,每个格子含图标 + 用户名(每行最多 5 个) |
| 多用户(仅图标) | customerList >20 个用户 | 方框内电能表网格,仅显示图标(格子更紧凑) |
交互:多用户箱内点击某个电表格 / 户名 = 选中该户(金圈高亮 +
customer-select/consumer:click), 点箱体空白 / 外框 = 选中整箱;悬停该户有青圈提示。用户端点(连接线)用客户档案assetNo引用即可。
客户数据格式(与拓扑 JSON 配套的 customer JSON):
[
{
"psrId": "4230000000109100079",
"consumerList": [
{ "consId": "...", "consName": "...", "realConsName": "张三", "meterId": "..." }
]
}
]
配套文件命名规则:拓扑文件为 XXX.json 时,客户文件为 XXXcustomer.json(Demo 模式下自动加载)。
TopoGraph 新增 Props
| Prop | 类型 | 默认 | 说明 |
|---|---|---|---|
customerData |
Array |
null |
客户数据数组,传入后自动注入到计量箱节点 |
工具函数
import { buildCustomerMap, injectCustomers, getMeterBoxSize } from 'topo-engine';
const customerMap = buildCustomerMap(customerJsonArray); // psrId → consumerList
injectCustomers(model, customerMap); // 注入到模型的 meterBox 节点
const size = getMeterBoxSize(node); // 获取动态尺寸 { w, h } | null
布局与渲染参数
computeOrthogonalLayout(model, options):
| 参数 | 默认 | 含义 |
|---|---|---|
nodeGap |
26 |
链上相邻节点边界间距 |
band |
50 |
侧分支根到父节点中心线的距离(分支带宽) |
packGap |
22 |
分支带内并排子分支间距 |
sideGap |
40 |
相邻主干节点的分支带隔离间距 |
margin |
40 |
画布外框留白 |
TopoGraph 组件内部即用上述默认参数,返回布局数据含每节点坐标、edgeCP(每条边的完整折线点序列)与 fishboneRibs,可配 assertOrthogonal(model, edgeCP) 做 0 交叉 / 正交性校验。
站房内部布局(含多母线)
站房(stations[].contain)内部按「进线开关 → 母线 → 出线开关」展开:
- 单母线:进线开关竖直在母线正上方,出线开关全部竖直均匀下挂母线,出线从开关底穿出框底。
- 多母线(双母线等):站内多条母线并排在同一水平线上(各自长度随本母线开关数量自适应); 母联开关沉到两母线间隙的下方,连线按**「半矩形(⊔)」走线——左母线端竖直向下 → 水平 → 母联开关 → 水平 → 竖直向上接右母线端 (电气方向与左右排列相反时自动翻转两侧,不横穿母线);母联短名为「母联」,标签居中画在 ⊔ 内部,不与相邻母线下的开关重叠; 其余开关按「父母线」归属,各自竖直下挂在自己母线上;站内根(如公变)与进线开关接在主母线(进线开关所接的那条母线)**上方; 站内只有变压器、没有进线开关时,变压器直接挂在主母线上方(也会正常定位,不会丢坐标)。
- 布局结果自动保证母线/母联/开关两两不重叠、线段横平竖直(
assertOrthogonal校验为 0 非正交段)。
TypeScript
类型声明随包发布(dist/index.d.ts),支持按需导入:
import { TopoApi, TopoGraph } from 'topo-engine';
import type { TopoApi } from 'topo-engine'; // 需要类型时
常见问题
- 图不显示 / 高度为 0:
TopoGraph撑满父容器(内部width/height: 100%),请给外层元素设置明确高度(如height: 600px)。 - 样式错乱 / 没有深色背景:确认已
import 'topo-engine/style.css'。 dataUrl加载失败:确认文件可被fetch访问(Vite 放public/,不要用相对路径);失败会触发error态显示并console.error。- 切换数据源:响应式修改
:data/:data-url会自动重新加载;本地文件可用ref.loadRaw(text)。 - 节点 ID 传字符串:内部统一按字符串存储(
String(id)),查询 API 请传字符串,如getNode('1')。 - 和 Vue 2 / 其它 G6 版本混用:仅支持 Vue 3.4+,图内部依赖
@antv/g6v5,请勿重复安装不同版本。
本地开发
npm install # 安装依赖
npm run dev # 开发演示(内置 API Playground,可试所有控制 API)→ http://127.0.0.1:5173/
npm run build # 生产构建(应用 + 库)
npm run build:lib # 仅构建库产物到 dist/
npm run preview # 预览生产构建
npm pack --dry-run # 查看发布包内容清单
License
MIT
Related Packages
A Vue 3 + SVG network topology graph component: node dragging, infinite pan & zo...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.1.12 | ^3.4.0 | MIT | |
| 0.1.11 | ^3.4.0 | MIT | |
| 0.1.10 | ^3.4.0 | MIT | |
| 0.1.9 | ^3.4.0 | MIT | |
| 0.1.8 | ^3.4.0 | MIT | |
| 0.1.7 | ^3.4.0 | MIT | |
| 0.1.6 | ^3.4.0 | MIT | |
| 0.1.5 | ^3.4.0 | MIT | |
| 0.1.4 | ^3.4.0 | MIT | |
| 0.1.3 | ^3.4.0 | MIT | |
| 0.1.2 | ^3.4.0 | MIT | |
| 0.1.0 | ^3.4.0 | MIT |