npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

irr-gh

v0.1.8

Published

灌溉系统概化图组件

Readme

irr-gh - 灌溉系统概化图组件

基于 Vue 3 + AntV G6 v5 的灌溉系统概化图可视化组件库。

目录


安装

npm install irr-gh
# 或
pnpm add irr-gh
# 或
bun add irr-gh

快速开始

组件导入方式

<script setup lang="ts">
import { ref } from 'vue'
import { IrrigationGraph } from 'irr-gh'
import 'irr-gh/style.css'
import type { IrrigationData } from 'irr-gh'

const graphRef = ref()

// 示例数据
const data: IrrigationData = {
  canals: [
    { id: 'main', name: '主干渠', type: 'canal', level: 1 },
    { id: 'branch-1', name: '支渠1', type: 'canal', parentId: 'main', bankSide: 'left' }
  ],
  points: [
    { id: 'sluice-1', name: '闸门1', type: 'sluice', canalId: 'main', chainage: 0 },
    { id: 'sluice-2', name: '闸门2', type: 'sluice', canalId: 'main', chainage: 100 }
  ]
}

function handleReady(graph: unknown) {
  console.log('图渲染完成', graph)
}
</script>

<template>
  <IrrigationGraph
    ref="graphRef"
    :data="data"
    :enable-minimap="true"
    :fit-view="true"
    :show-toolbar="true"
    @ready="handleReady"
  />
</template>

全局注册方式

您也可以在 main.js/main.ts 中全局注册组件:

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import IrrGh from 'irr-gh'
import 'irr-gh/style.css'

const app = createApp(App)

// 全局注册组件
app.use(IrrGh)

app.mount('#app')

之后就可以在任何组件中直接使用 <IrrigationGraph> 组件,无需单独导入:

<script setup lang="ts">
import { ref } from 'vue'
import type { IrrigationData } from 'irr-gh'

const graphRef = ref()

// 示例数据
const data: IrrigationData = {
  canals: [
    { id: 'main', name: '主干渠', type: 'canal', level: 1 },
    { id: 'branch-1', name: '支渠1', type: 'canal', parentId: 'main', bankSide: 'left' }
  ],
  points: [
    { id: 'sluice-1', name: '闸门1', type: 'sluice', canalId: 'main', chainage: 0 },
    { id: 'sluice-2', name: '闸门2', type: 'sluice', canalId: 'main', chainage: 100 }
  ]
}

function handleReady(graph: unknown) {
  console.log('图渲染完成', graph)
}
</script>

<template>
  <IrrigationGraph
    ref="graphRef"
    :data="data"
    :enable-minimap="true"
    :fit-view="true"
    :show-toolbar="true"
    @ready="handleReady"
  />
</template>

布局系统

布局方向

组件支持两种布局方向:

| 布局类型 | 值 | 说明 | |---------|------|------| | 横向布局 | 'horizontal' | 主干渠从左到右水平排列,支渠向上/下垂直分叉 | | 纵向布局 | 'vertical' | 主干渠从上到下垂直排列,支渠向左/右水平分叉 |

布局规则

1. 主干渠方向决定布局

  • 横向布局:主干渠从左到右水平绘制
  • 纵向布局:主干渠从上到下垂直绘制

2. 支渠垂直相交原则

支渠始终与父级渠道垂直相交:

横向布局时:

  • 父级水平 → 子级垂直
  • 左岸(bankSide: 'left')→ 向上分叉
  • 右岸(bankSide: 'right')→ 向下分叉

纵向布局时:

  • 父级垂直 → 子级水平
  • 左岸(bankSide: 'left')→ 向左分叉
  • 右岸(bankSide: 'right')→ 向右分叉

3. 主干渠居中

主干渠自动居中到画布中心位置。

布局间距配置

interface LayoutSpacing {
  /** 主渠方向节点间距 */
  main: number        // 默认: 150
  /** 支渠方向节点间距 */
  branch: number      // 默认: 120
  /** 分支偏移距离 */
  branchOffset: number // 默认: 80
}

组件配置

Props 属性

| 属性 | 类型 | 默认值 | 说明 | |------|------|--------|------| | width | number | - | 画布宽度(不设置则自适应容器) | | height | number | - | 画布高度(不设置则自适应容器) | | data | IrrigationData | - | 业务数据(原始格式) | | graphData | IrrigationGraphData | - | G6图数据(已转换格式) | | layout | LayoutConfig | - | 布局配置 | | theme | ThemeConfig | - | 主题配置 | | tooltip | TooltipConfig | - | Tooltip配置 | | dataPanel | DataPanelConfig | - | 常显数据面板配置 | | enableDrag | boolean | true | 是否启用拖拽 | | enableZoom | boolean | true | 是否启用缩放 | | enableBrush | boolean | false | 是否启用框选 | | enableMinimap | boolean | false | 是否启用小地图 | | fitView | boolean | true | 是否适应画布 | | fitViewPadding | number \| number[] | - | 适应画布的内边距 | | readonly | boolean | false | 是否只读模式 | | showToolbar | boolean | false | 是否显示内置工具栏 | | enabledToolbarActions | ToolbarActions | 全部启用 | 启用的工具栏功能 | | evolution | EvolutionConfig | - | 演进功能配置 | | evolutionData | EvolutionData | - | 演进数据 |

ToolbarActions 配置

interface ToolbarActions {
  zoomIn?: boolean   // 放大按钮
  zoomOut?: boolean  // 缩小按钮
  fitView?: boolean  // 适应视图按钮
  save?: boolean     // 保存按钮
  export?: boolean   // 导出按钮
  print?: boolean    // 打印按钮
  layout?: boolean   // 布局切换按钮
}

DataPanelConfig 配置

常显数据面板配置,仅在点位节点上显示,当启用时会自动禁用 Tooltip。

interface DataPanelConfig {
  enabled?: boolean              // 是否启用,默认 false
  formatter?: (data: IrrigationNodeData) => string  // 自定义内容格式化(返回 HTML 字符串)
  offsetX?: number               // 水平偏移,默认 10
  offsetY?: number               // 垂直偏移,默认 -10
}

使用示例:

<script setup>
import { ref } from 'vue'

const dataPanelConfig = ref({
  enabled: true,
  formatter: (nodeData) => {
    const label = nodeData.data?.label || nodeData.id
    const entityType = nodeData.entityType || '未知类型'
    
    return `
      <div style="font-weight: bold; color: #1890ff;">${label}</div>
      <div style="color: #666; font-size: 11px;">类型: ${entityType}</div>
      <div style="color: #999; font-size: 10px;">状态: 正常</div>
    `
  },
  offsetX: 0,
  offsetY: -15
})
</script>

<template>
  <IrrigationGraph :data="data" :data-panel="dataPanelConfig" />
</template>

Events 事件

| 事件名 | 参数 | 说明 | |--------|------|------| | ready | (graph: Graph) | 图渲染完成 | | itemClick | ({ type: string, item: unknown }) | 节点/边点击 | | itemDblClick | ({ type: string, item: unknown }) | 节点/边双击 | | itemContextMenu | ({ type: string, item: unknown, event: MouseEvent }) | 节点/边右键菜单 | | selectionChange | ({ nodes: string[], edges: string[] }) | 选中状态变化 | | canvasClick | (event: MouseEvent) | 画布点击 | | evolutionChange | (params: EvolutionEventParams) | 演进状态/时间点变化 | | dataChange | (data: IrrigationGraphData) | 数据变化 |

Slots 插槽

| 插槽名 | 参数 | 说明 | |--------|------|------| | toolbar | { zoomIn, zoomOut, fitView } | 自定义工具栏 | | loading | - | 自定义加载状态 | | default | - | 默认插槽,用于额外内容 |


API 方法

通过 ref 获取组件实例调用方法:

<script setup>
const graphRef = ref()

// 调用方法
graphRef.value?.zoomIn()
</script>

<template>
  <IrrigationGraph ref="graphRef" />
</template>

数据操作

| 方法 | 签名 | 说明 | |------|------|------| | render | (data: IrrigationGraphData) => Promise<void> | 渲染G6格式数据 | | renderFromData | (data: IrrigationData, direction?: LayoutDirection) => Promise<void> | 从业务数据渲染 | | updateData | (data: Partial<IrrigationGraphData>) => Promise<void> | 更新数据 | | addNode | (node: IrrigationNodeData) => Promise<void> | 添加节点 | | addEdge | (edge: IrrigationEdgeData) => Promise<void> | 添加边 | | removeNode | (nodeId: string) => Promise<void> | 删除节点 | | removeEdge | (edgeId: string) => Promise<void> | 删除边 | | updateNode | (nodeId: string, data: Partial<IrrigationNodeData>) => Promise<void> | 更新节点 | | updateEdge | (edgeId: string, data: Partial<IrrigationEdgeData>) => Promise<void> | 更新边 | | setEvolutionData | (data: EvolutionData) => void | 设置/更新演进数据 | | getEvolutionManager | () => EvolutionManager | 获取演进管理器实例 | | getData | () => IrrigationGraphData | 获取当前图数据 |

视图控制

| 方法 | 签名 | 说明 | |------|------|------| | zoomIn | () => void | 放大视图 | | zoomOut | () => void | 缩小视图 | | zoomTo | (ratio: number) => void | 缩放到指定比例 | | fitView | () => void | 适应视图 | | focusNode | (nodeId: string) => void | 聚焦到指定节点 |

布局操作

| 方法 | 签名 | 说明 | |------|------|------| | changeLayout | (type: 'horizontal' \| 'vertical') => Promise<void> | 切换布局方向 | | changeLayoutDirection | (data: IrrigationData, direction: LayoutDirection) => Promise<void> | 使用新布局方向重新渲染 | | setLayout | (layout: LayoutConfig) => Promise<void> | 设置G6布局配置 |

导出与保存

| 方法 | 签名 | 说明 | |------|------|------| | save | () => string | 保存为JSON字符串 | | load | (json: string) => Promise<void> | 从JSON加载 | | toImage | (config?: ExportConfig) => Promise<string> | 导出为图片(Base64) | | downloadImage | (config?: ExportConfig) => Promise<void> | 下载图片 | | print | () => void | 打印 |

ExportConfig 配置

interface ExportConfig {
  fileName?: string      // 文件名,默认: 'irrigation-graph'
  format?: 'png' | 'jpg' | 'svg' | 'pdf'  // 导出格式
  backgroundColor?: string  // 背景色
  scale?: number         // 缩放比例
}

事件监听

| 方法 | 签名 | 说明 | |------|------|------| | on | (type: InteractionEventType, handler: Function) => void | 监听事件 | | off | (type: InteractionEventType, handler?: Function) => void | 移除事件监听 |

可监听的事件类型

type InteractionEventType =
  | 'node:click' | 'node:dblclick' | 'node:contextmenu'
  | 'node:mouseenter' | 'node:mouseleave'
  | 'node:dragstart' | 'node:drag' | 'node:dragend'
  | 'edge:click' | 'edge:dblclick' | 'edge:contextmenu'
  | 'edge:mouseenter' | 'edge:mouseleave'
  | 'canvas:click' | 'canvas:dragstart' | 'canvas:drag' | 'canvas:dragend'
  | 'combo:click' | 'combo:dblclick'

数据结构

业务数据结构

interface IrrigationData {
  /** 河渠沟列表 */
  canals: CanalEntity[]
  /** 点位实体列表 */
  points: PointEntityUnion[]
  /** 连接关系(可选,如不提供则自动生成) */
  connections?: ConnectionData[]
}

实体类型

渠道实体 (CanalEntity)

interface CanalEntity {
  id: string              // 唯一标识
  name: string            // 名称
  type: 'canal'           // 实体类型
  parentId?: string       // 父级河渠沟ID
  forkChainage?: number   // 上级分岔口桩号
  bankSide?: 'left' | 'right' | 'center'  // 岸别
  startChainage?: number  // 起始桩号
  endChainage?: number    // 终止桩号
  level?: number          // 河渠等级
  properties?: Record<string, unknown>  // 扩展属性
}

点位实体类型

| 类型 | 说明 | 特有属性 | |------|------|----------| | sluice | 闸门 | sluiceType, designFlow | | pumpStation | 泵站 | capacity, pumpType | | reservoir | 水库 | storageCapacity, normalLevel | | dispatchUnit | 调度单元 | controlArea | | dispatchNode | 调度节点 | nodeFunction | | auxiliary | 辅助节点 | auxiliaryType (fork/end/junction) |

点位实体基础结构

interface PointEntity {
  id: string              // 唯一标识
  name: string            // 名称
  type: EntityType        // 实体类型
  canalId: string         // 所属河渠沟ID
  chainage: number        // 桩号位置
  bankSide?: 'left' | 'right' | 'center'  // 岸别
  properties?: Record<string, unknown>  // 扩展属性
  /** 节点显示配置(可选,用于自定义节点的G6渲染样式) */
  nodeConfig?: PointNodeConfig
}

节点显示配置 (PointNodeConfig)

您可以使用 nodeConfig 属性来自定义节点的显示样式:

interface PointNodeConfig {
  /** 节点形状: rect(矩形), circle(圆形), diamond(菱形), image(图片) */
  shape?: 'rect' | 'circle' | 'diamond' | 'ellipse' | 'image'
  /** 图片地址(shape为image时使用) */
  img?: string
  /** 节点宽度 */
  width?: number
  /** 节点高度 */
  height?: number
  /** 填充色 */
  fill?: string
  /** 边框色 */
  stroke?: string
  /** 边框宽度 */
  lineWidth?: number
  /** 圆角半径 */
  radius?: number
}

使用示例:

// 使用图片节点
const sluiceWithImage: SluiceEntity = {
  id: 'slu-1',
  name: '进水闸1',
  type: 'sluice',
  canalId: 'canal-A',
  chainage: 0,
  sluiceType: 'inlet',
  designFlow: 50,
  nodeConfig: {
    shape: 'image',
    img: '/head.png',
    width: 48,
    height: 48
  }
}

// 使用矩形节点并自定义样式
const pumpWithCustomStyle: PumpStationEntity = {
  id: 'pump-1',
  name: '提水泵站1',
  type: 'pumpStation',
  canalId: 'canal-B',
  chainage: 100,
  capacity: 500,
  pumpType: 'lift',
  nodeConfig: {
    shape: 'rect',
    width: 60,
    height: 40,
    fill: '#ffccc7',
    stroke: '#ff4d4f',
    radius: 8
  }
}

// 使用圆形节点
const reservoirWithCircle: ReservoirEntity = {
  id: 'reservoir-1',
  name: '调节水库1',
  type: 'reservoir',
  canalId: 'canal-C',
  chainage: 500,
  storageCapacity: 10000,
  normalLevel: 85,
  nodeConfig: {
    shape: 'circle',
    r: 24,  // 圆形使用 r 属性表示半径
    fill: '#e6f7ff',
    stroke: '#1890ff'
  }
}

辅助节点 (用于支渠分叉)

interface AuxiliaryNodeEntity extends PointEntity {
  type: 'auxiliary'
  auxiliaryType: 'fork' | 'end' | 'junction'  // 分叉点/结束点/汇合点
  branchCanalId?: string  // 关联的支渠ID(分叉点使用)
  autoGenerated?: boolean // 是否自动生成
}

G6 图数据结构

interface IrrigationGraphData {
  nodes?: IrrigationNodeData[]
  edges?: IrrigationEdgeData[]
  combos?: IrrigationComboData[]
}

interface IrrigationNodeData extends NodeData {
  entityType: EntityType              // 业务实体类型
  businessData?: IrrigationEntity     // 原始业务数据
  nodeShape?: 'rect' | 'circle' | 'ellipse' | 'diamond' | 'image'
  styleConfig?: NodeStyleConfig
  labelConfig?: LabelStyleConfig
}

interface IrrigationEdgeData extends EdgeData {
  edgeShape?: 'line' | 'polyline' | 'quadratic' | 'cubic' | 'arc'
  connectionType?: 'flow' | 'control' | 'supply'
  styleConfig?: EdgeStyleConfig
  labelConfig?: LabelStyleConfig
}

工具栏

内置工具栏

通过 showToolbar 属性启用内置工具栏:

<IrrigationGraph
  :show-toolbar="true"
  :enabled-toolbar-actions="{
    zoomIn: true,
    zoomOut: true,
    fitView: true,
    save: true,
    export: true,
    print: true,
    layout: true
  }"
/>

自定义工具栏

使用 toolbar 插槽自定义工具栏:

<IrrigationGraph ref="graphRef">
  <template #toolbar="{ zoomIn, zoomOut, fitView }">
    <div class="my-toolbar">
      <button @click="zoomIn">放大</button>
      <button @click="zoomOut">缩小</button>
      <button @click="fitView">适应</button>
      <button @click="graphRef?.changeLayout('horizontal')">横向</button>
      <button @click="graphRef?.changeLayout('vertical')">纵向</button>
    </div>
  </template>
</IrrigationGraph>

主题配置

默认样式常量

// 渠道/边的默认宽度
export const CANAL_WIDTH = 10

// 渠道默认颜色
export const CANAL_COLOR = '#1890ff'

辅助节点样式

辅助节点(分叉点、结束点、汇合点)样式与渠道保持一致:

  • 形状:正方形(rect)
  • 尺寸:10 × 10 像素(与渠道宽度一致)
  • 颜色:与渠道颜色一致(#1890ff)
  • 无边框、无圆角

节点形状类型

支持以下节点形状:

| 形状 | 值 | 说明 | |------|------|------| | 矩形 | 'rect' | 默认形状,可设置圆角 radius | | 圆形 | 'circle' | 圆形节点 | | 菱形 | 'diamond' | 菱形节点 | | 椭圆 | 'ellipse' | 椭圆节点 | | 图片 | 'image' | 使用图片作为节点,需配置 img 属性 | | 自定义 | 'custom' | 自定义节点形状 |

默认节点样式映射

| 实体类型 | 默认形状 | 填充色 | 边框色 | |----------|----------|--------|--------| | sluice (闸门) | rect | #fffbe6 | #faad14 | | pumpStation (泵站) | rect | #f6ffed | #52c41a | | reservoir (水库) | circle | #e6fffb | #13c2c2 | | dispatchUnit (调度单元) | diamond | #f9f0ff | #722ed1 | | dispatchNode (调度节点) | circle | #fff0f6 | #eb2f96 | | auxiliary (辅助节点) | rect | #1890ff | #1890ff |

图片类型节点

点位节点支持使用图片,通过业务数据中的 nodeConfig 配置(推荐方式),或通过 G6 图数据中的 styleConfig.img 配置:

// 业务数据中的节点配置(推荐方式)
const sluiceWithImage: SluiceEntity = {
  id: 'gate-1',
  name: '进水闸',
  type: 'sluice',
  canalId: 'canal-1',
  chainage: 0,
  sluiceType: 'inlet',
  // 通过 nodeConfig 指定节点渲染样式
  nodeConfig: {
    shape: 'image',
    img: '/head.png',
    width: 48,
    height: 48
  }
}

// 其他类型的图片配置
const pumpStationWithImage: PumpStationEntity = {
  id: 'pump-1',
  name: '泵站',
  type: 'pumpStation',
  canalId: 'canal-1',
  chainage: 100,
  capacity: 500,
  pumpType: 'lift',
  nodeConfig: {
    shape: 'image',
    img: '/pump-station.png',
    width: 48,
    height: 48
  }
}

// 普通矩形节点配置
const sluiceWithRect: SluiceEntity = {
  id: 'gate-2',
  name: '普通闸门',
  type: 'sluice',
  canalId: 'canal-1',
  chainage: 200,
  sluiceType: 'other',
  nodeConfig: {
    shape: 'rect',
    width: 48,
    height: 36,
    fill: '#fffbe6',
    stroke: '#faad14'
  }
}

// G6图数据(转换后)
const nodeData: IrrigationNodeData = {
  id: 'gate-1',
  entityType: 'sluice',
  nodeShape: 'image',  // 从 nodeConfig.shape 得到
  styleConfig: {
    img: '/head.png',  // 从 nodeConfig.img 得到
    width: 48,
    height: 48,
    fill: '#fffbe6',
    stroke: '#faad14'
  },
  data: { label: '进水闸' },
  businessData: sluiceWithImage  // 保留原始业务数据
}

边/渠道样式

默认渠道样式:

  • 宽度:10 像素
  • 颜色:#1890ff
  • 无箭头:默认不显示箭头

连接类型样式:

| 连接类型 | 颜色 | 宽度 | 样式 | |----------|------|------|------| | flow (水流) | #1890ff | 10px | 实线 | | control (控制) | #faad14 | 3px | 虚线 [8, 4] | | supply (供水) | #52c41a | 3px | 虚线 [6, 4] |

主题配置接口

interface ThemeConfig {
  name?: 'light' | 'dark' | 'custom'
  nodeStyle?: Partial<Record<EntityType, NodeStyleConfig>>
  edgeStyle?: EdgeStyleConfig
  backgroundColor?: string
}

interface NodeStyleConfig {
  fill?: string          // 填充色
  stroke?: string        // 边框色
  lineWidth?: number     // 边框宽度
  opacity?: number       // 透明度
  radius?: number        // 圆角半径
  width?: number         // 宽度
  height?: number        // 高度
  shadowColor?: string   // 阴影颜色
  shadowBlur?: number    // 阴影模糊度
}

interface EdgeStyleConfig {
  stroke?: string        // 线条颜色
  lineWidth?: number     // 线条宽度
  lineDash?: number[]    // 虚线配置
  opacity?: number       // 透明度
  endArrow?: boolean     // 结束箭头
  startArrow?: boolean   // 起始箭头
}

使用示例

<IrrigationGraph
  :theme="{
    name: 'custom',
    backgroundColor: '#f5f5f5',
    nodeStyle: {
      sluice: { fill: '#1890ff', stroke: '#0050b3' },
      pumpStation: { fill: '#52c41a', stroke: '#237804' },
      reservoir: { fill: '#722ed1', stroke: '#391085' }
    },
    edgeStyle: {
      stroke: '#333',
      lineWidth: 2
    }
  }"
/>

Hook 使用

可以直接使用 useIrrigationGraph Hook 获得更灵活的控制:

<script setup lang="ts">
import { ref } from 'vue'
import { useIrrigationGraph } from 'irr-gh'

const containerRef = ref<HTMLElement | null>(null)

const {
  graph,
  manager,
  state,
  initialized,
  loading,
  init,
  render,
  renderFromData,
  changeLayoutDirection,
  zoomIn,
  zoomOut,
  fitView,
  getData,
  save,
  load,
  toImage,
  downloadImage,
  print,
  on,
  off,
  destroy
} = useIrrigationGraph({
  container: containerRef,
  width: 1200,
  height: 800,
  data: myData,
  layoutDirection: 'horizontal',
  autoInit: true,
  options: {
    enableDrag: true,
    enableZoom: true,
    enableMinimap: true
  }
})
</script>

<template>
  <div ref="containerRef" style="width: 100%; height: 600px;"></div>
</template>

Hook 配置选项

interface UseIrrigationGraphOptions {
  container: Ref<HTMLElement | null>  // 容器元素引用
  width?: number                      // 画布宽度
  height?: number                     // 画布高度
  data?: IrrigationData               // 初始业务数据
  graphData?: IrrigationGraphData     // 初始G6数据
  options?: Partial<GraphOptions>     // 图配置选项
  autoInit?: boolean                  // 是否自动初始化(默认true)
  layoutDirection?: LayoutDirection   // 初始布局方向(默认horizontal)
}

布局辅助工具

组件暴露了 layoutUtils 对象,提供布局辅助函数:

// 通过组件实例访问
graphRef.value?.layoutUtils

// 可用方法
layoutUtils.getNodePosition(node)           // 获取节点位置
layoutUtils.setNodePosition(node, x, y)     // 设置节点位置
layoutUtils.alignNodesHorizontally(nodes, alignType)  // 水平对齐
layoutUtils.alignNodesVertically(nodes, alignType)    // 垂直对齐
layoutUtils.distributeNodesHorizontally(nodes, spacing) // 水平等距分布
layoutUtils.distributeNodesVertically(nodes, spacing)   // 垂直等距分布
layoutUtils.moveNodes(nodes, deltaX, deltaY)  // 批量移动节点
layoutUtils.getNodesBoundingBox(nodes)        // 获取节点边界框
layoutUtils.centerNodesToPosition(nodes, x, y) // 居中节点到位置
layoutUtils.centerNodesToCanvas(nodes, width, height) // 居中节点到画布
layoutUtils.flipNodes(nodes, axis)            // 翻转节点
layoutUtils.rotateNodes90(nodes, clockwise)   // 旋转90度
layoutUtils.getNodesByCanalId(data, canalId)  // 按渠道ID获取节点
layoutUtils.getConnectedNodes(data, nodeId)   // 获取相邻节点
layoutUtils.autoAdjustSpacing(nodes, direction, spacing) // 自动调整间距

数据演进

组件内置了数据演进功能,支持展示随时间变化的节点状态(如水位报警)和边状态(如流向、流量渐变)。

核心特性

  • 时序播放:支持自动/手动播放时间序列数据。
  • 报警级别映射:根据 alarmLevel 自动更新节点填充色、边框色和呼吸灯效果(阴影)。
  • 边渐变色流向:支持根据流向(正向/反向)自动计算边渐变方向,并根据状态实时更新。
  • 自定义数据面板:演进过程中的业务数据可在常显面板中实时展示。

演进配置 (EvolutionConfig)

interface EvolutionConfig {
  enabled?: boolean           // 是否启用
  interval?: number          // 播放速度(毫秒/帧),默认 2000
  loop?: boolean              // 是否循环播放
  autoPlay?: boolean          // 是否自动播放
  alarmStyles?: Partial<AlarmStyleMap> // 覆盖默认报警样式
  defaultGradient?: EdgeGradientConfig // 边默认渐变配置
}

数据结构

interface EvolutionData {
  timePoints: EvolutionTimePoint[]
}

interface EvolutionTimePoint {
  timestamp: number | string  // 时间戳或 ISO 字符串
  label?: string              // 时间显示标签,如 "08:00"
  nodeStates?: Record<string, NodeEvolutionState> // 节点状态映射
  edgeStates?: Record<string, EdgeEvolutionState> // 边状态映射
}

interface NodeEvolutionState {
  alarmLevel?: 'normal' | 'warning' | 'error' | 'critical'
  data?: Record<string, unknown> // 实时业务数据
  style?: NodeEvolutionStyle     // 自定义样式覆盖
}

interface EdgeEvolutionState {
  flowDirection?: 'forward' | 'backward' // 流向
  gradient?: { startColor: string; endColor: string } // 渐变配置
}

使用示例

<script setup>
import { ref } from 'vue'
import { createEvolutionMockData } from './mock'

const evolutionConfig = {
  enabled: true,
  interval: 1500,
  loop: true
}

const evolutionData = createEvolutionMockData()
</script>

<template>
  <IrrigationGraph 
    :data="baseData" 
    :evolution="evolutionConfig"
    :evolution-data="evolutionData"
  />
</template>

完整示例

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { IrrigationGraph } from 'irr-gh'
import 'irr-gh/style.css'
import type { IrrigationData } from 'irr-gh'

const graphRef = ref()

// 完整示例数据
const demoData: IrrigationData = {
  canals: [
    { id: 'main', name: '总干渠', type: 'canal', level: 1 },
    { id: 'branch-A', name: 'A支渠', type: 'canal', parentId: 'main', bankSide: 'left', level: 2 },
    { id: 'branch-B', name: 'B支渠', type: 'canal', parentId: 'main', bankSide: 'right', level: 2 }
  ],
  points: [
    // 总干渠上的点位
    { id: 'intake', name: '进水闸', type: 'sluice', canalId: 'main', chainage: 0 },
    { id: 'fork-A', name: 'A分叉', type: 'auxiliary', auxiliaryType: 'fork', canalId: 'main', chainage: 100, branchCanalId: 'branch-A' },
    { id: 'pump-1', name: '1号泵站', type: 'pumpStation', canalId: 'main', chainage: 200 },
    { id: 'fork-B', name: 'B分叉', type: 'auxiliary', auxiliaryType: 'fork', canalId: 'main', chainage: 300, branchCanalId: 'branch-B' },
    { id: 'outlet', name: '出水闸', type: 'sluice', canalId: 'main', chainage: 400 },
    
    // A支渠上的点位
    { id: 'sluice-A1', name: 'A1闸门', type: 'sluice', canalId: 'branch-A', chainage: 0 },
    { id: 'reservoir-A', name: 'A水库', type: 'reservoir', canalId: 'branch-A', chainage: 50 },
    
    // B支渠上的点位
    { id: 'sluice-B1', name: 'B1闸门', type: 'sluice', canalId: 'branch-B', chainage: 0 },
    { id: 'dispatch-B', name: 'B调度单元', type: 'dispatchUnit', canalId: 'branch-B', chainage: 50 }
  ]
}

// 事件处理
function handleReady(graph: unknown) {
  console.log('图渲染完成')
}

function handleItemClick({ type, item }: { type: string; item: unknown }) {
  console.log(`点击了${type}:`, item)
}

function handleCanvasClick(event: MouseEvent) {
  console.log('画布点击', event)
}

// API 操作示例
function switchToHorizontal() {
  graphRef.value?.changeLayout('horizontal')
}

function switchToVertical() {
  graphRef.value?.changeLayout('vertical')
}

function exportImage() {
  graphRef.value?.downloadImage({ fileName: 'irrigation-diagram' })
}
</script>

<template>
  <div class="app">
    <IrrigationGraph
      ref="graphRef"
      :data="demoData"
      :enable-minimap="true"
      :fit-view="true"
      :show-toolbar="true"
      :enabled-toolbar-actions="{
        zoomIn: true,
        zoomOut: true,
        fitView: true,
        save: true,
        export: true,
        print: true,
        layout: true
      }"
      @ready="handleReady"
      @item-click="handleItemClick"
      @canvas-click="handleCanvasClick"
    />
  </div>
</template>

<style>
.app {
  width: 100vw;
  height: 100vh;
}
</style>

类型导出

// 从 irr-gh 导入类型
import type {
  // 业务数据类型
  IrrigationData,
  CanalEntity,
  PointEntityUnion,
  SluiceEntity,
  PumpStationEntity,
  ReservoirEntity,
  DispatchUnitEntity,
  DispatchNodeEntity,
  AuxiliaryNodeEntity,
  ConnectionData,
  EntityType,
  
  // 图数据类型
  IrrigationGraphData,
  IrrigationNodeData,
  IrrigationEdgeData,
  IrrigationComboData,
  
  // 演进数据类型
  EvolutionData,
  EvolutionConfig,
  EvolutionTimePoint,
  EvolutionEventParams,
  
  // 配置与Props
  IrrigationGraphProps,
  GraphOptions,
  LayoutConfig,
  ThemeConfig,
  TooltipConfig,
  DataPanelConfig,
  ExportConfig,
  
  // 布局与交互
  LayoutDirection,
  LayoutSpacing,
  InteractionEventType,
  InteractionEventHandler
} from 'irr-gh'

License

MIT