Skip to content
索引

起步

logic-flow是一个开发流程图的库

搜索引擎有可能搜到的是旧版官方文档,啪的一下点进去,很快啊,照着文档一顿搞,结果各种不生效,去github一看,哎不是最新文档,去骗去偷袭我一个练习时长两年半的前端练习生

新旧版文档内容变更比较大,旧版文档的一些代码思路还是值得参考的,新版文档中可能就没有这些内容

旧版官方文档 https://07.logic-flow.cn/

官方文档 https://docs.logic-flow.cn/docs/#/zh/guide/start

用法

安装

安装核心库和插件库

sh
npm i @logicflow/core @logicflow/extension -s 
npm i @logicflow/core @logicflow/extension -s 

安装完导入jscss

js
import { LogicFlow } from "@logicflow/core"
import "@logicflow/core/dist/style/index.css"
import { LogicFlow } from "@logicflow/core"
import "@logicflow/core/dist/style/index.css"

创建容器

在页面中指定一个html元素作为绘图的容器,又称画布,比如一个 div 标签

html
<div id="container"></div>
<div id="container"></div>

准备数据

通过 JSON 的数据格式,来让 LogicFlow 渲染。该数据中需要有 nodes(节点) 和 edges(边) 字段,分别用数组表示:

实际开发中,用户自己创建一个流程图,前端使用LogicFlow导出如下数据格式流程图数据,保存至后端数据库,下次请求再获取并渲染流程图

js
const data = {
  // 节点
  nodes: [
    {
      id: 21,
      type: 'rect',
      x: 100,
      y: 200,
      text: {
        value: '矩形节点',
        x: 100,
        y: 200,
      },
    },
    {
      id: 50,
      type: 'circle',
      x: 300,
      y: 400,
      text: {
        value: '圆形节点',
        x: 300,
        y: 400,
      },
    },
  ],
  // 边
  edges:[
    {
      type: 'polyline',
      sourceNodeId: 50,
      targetNodeId: 21,
    }
  ]
}
const data = {
  // 节点
  nodes: [
    {
      id: 21,
      type: 'rect',
      x: 100,
      y: 200,
      text: {
        value: '矩形节点',
        x: 100,
        y: 200,
      },
    },
    {
      id: 50,
      type: 'circle',
      x: 300,
      y: 400,
      text: {
        value: '圆形节点',
        x: 300,
        y: 400,
      },
    },
  ],
  // 边
  edges:[
    {
      type: 'polyline',
      sourceNodeId: 50,
      targetNodeId: 21,
    }
  ]
}

渲染画布

创建一个 LogicFlow 的实例,此时可以传入一些参数来控制画布,比如画布的大小,最后渲染数据

js
const lf = new LogicFlow({
  container: document.querySelector('#container'),
  width: 700,
  height: 600
})
const lf = new LogicFlow({
  container: document.querySelector('#container'),
  width: 700,
  height: 600
})

通过刚才创建的实例数据渲染到画布上

js
lf.render(data)
lf.render(data)

vue完整示例代码

vue
<script setup lang="ts">
import { LogicFlow } from '@logicflow/core'
import '@logicflow/core/dist/style/index.css'
import { onMounted } from 'vue'
const data = {
  // 节点
  nodes: [
    {
      id: 21,
      type: 'rect',
      x: 100,
      y: 200,
      text: {
        value: '矩形节点',
        x: 100,
        y: 200
      }
    },
    {
      id: 50,
      type: 'circle',
      x: 300,
      y: 400,
      text: {
        value: '圆形节点',
        x: 300,
        y: 400
      }
    }
  ],
  // 边
  edges: [
    {
      type: 'polyline',
      sourceNodeId: 50,
      targetNodeId: 21
    }
  ]
}
onMounted(() => {
  const lf = new LogicFlow({
    container: document.querySelector('#container') as HTMLElement,
    width: 700,
    height: 600
  })
  lf.render(data)
})
</script>

<template>
  <div id="container"></div>
</template>

<style scoped></style>
<script setup lang="ts">
import { LogicFlow } from '@logicflow/core'
import '@logicflow/core/dist/style/index.css'
import { onMounted } from 'vue'
const data = {
  // 节点
  nodes: [
    {
      id: 21,
      type: 'rect',
      x: 100,
      y: 200,
      text: {
        value: '矩形节点',
        x: 100,
        y: 200
      }
    },
    {
      id: 50,
      type: 'circle',
      x: 300,
      y: 400,
      text: {
        value: '圆形节点',
        x: 300,
        y: 400
      }
    }
  ],
  // 边
  edges: [
    {
      type: 'polyline',
      sourceNodeId: 50,
      targetNodeId: 21
    }
  ]
}
onMounted(() => {
  const lf = new LogicFlow({
    container: document.querySelector('#container') as HTMLElement,
    width: 700,
    height: 600
  })
  lf.render(data)
})
</script>

<template>
  <div id="container"></div>
</template>

<style scoped></style>

网格配置

https://docs.logic-flow.cn/docs/#/zh/api/logicFlowApi?id=grid

网格,若设为false不开启网格,则为 1px 移动单位,不绘制网格背景,若设置为true开启则默认为 20px 点状网格

false | Object,默认 false

js
  const lf = new LogicFlow({
    container: document.querySelector('#container') as HTMLElement,
    width: 700,
    height: 600,
    grid: true
  })
  const lf = new LogicFlow({
    container: document.querySelector('#container') as HTMLElement,
    width: 700,
    height: 600,
    grid: true
  })

画布设置

画布宽高

如果不设置画布宽高,默认是容器的宽高

html
<div id="container"></div>
<div id="container"></div>
css
#container {
  width: 100%;
  height: 100%;
  }
#container {
  width: 100%;
  height: 100%;
  }

设置画布固定宽高

js
const lf = new LogicFlow({
      container: document.querySelector("#container"),
      width: 700,
      height: 600,
    })
const lf = new LogicFlow({
      container: document.querySelector("#container"),
      width: 700,
      height: 600,
    })

主题

  • stroke 边框颜色
  • stroke-dasharray 边框间隔图案
  • stroke-width 边框宽度
  • fill 图形元素内部的颜色
  • fill-opacity 填色的不透明度或当前对象的内容物的不透明度
  • font-size 文本字体大小
  • color 文本颜色

setTheme设置主题

js
lf.setTheme({
      nodeText: {
        color: "#ffffff",
        overflowMode: "autoWrap",
        fontSize: 15
      },
      edgeText: {
        textWidth: 50,
        overflowMode: "autoWrap",
        fontSize: 12,
        background: {
          fillOpacity: 0
        }
      }
    })
lf.setTheme({
      nodeText: {
        color: "#ffffff",
        overflowMode: "autoWrap",
        fontSize: 15
      },
      edgeText: {
        textWidth: 50,
        overflowMode: "autoWrap",
        fontSize: 12,
        background: {
          fillOpacity: 0
        }
      }
    })

拖拽菜单

https://docs.logic-flow.cn/docs/#/zh/guide/extension/component-dnd-panel

vue示例

vite+vue3

vue
<script setup lang="ts">
import { LogicFlow } from '@logicflow/core'
import '@logicflow/core/dist/style/index.css'
import { Control, Menu, DndPanel, SelectionSelect, Snapshot } from '@logicflow/extension'
import '@logicflow/extension/lib/style/index.css'
LogicFlow.use(DndPanel)
import { onMounted } from 'vue'
import one from './node/one'
import two from './node/two'
import three from './node/three'
import four from './node/four'
import five from './node/five'
import six from './node/six'
const registerCustomElement = (lf) => {
  lf.register(one)
  lf.register(two)
  lf.register(three)
  lf.register(four)
  lf.register(five)
  lf.register(six)
}

const data = {
  // 节点
  nodes: [
    {
      id: 1,
      type: 'image-one',
      x: 300,
      y: 200,
      text: '地调一平面'
    },
    {
      id: 2,
      type: 'image-two',
      x: 300,
      y: 300,
      text: '一平面路由器'
    },
    {
      id: 3,
      type: 'image-three',
      x: 500,
      y: 600,
      text: '一平面一区纵向'
    },
    {
      id: 4,
      type: 'image-four',
      x: 300,
      y: 600,
      text: '一平面一区交换机'
    }
  ],
  // 边
  edges: [
    {
      type: 'polyline',
      sourceNodeId: 1,
      targetNodeId: 2
    }
  ]
}
onMounted(() => {
  const lf = new LogicFlow({
    container: document.querySelector('#container') as HTMLElement,
    width: 1300,
    height: 900,
    grid: true
  })
  lf.extension.dndPanel.setPatternItems([
    {
      label: '选区',
      icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAAH6ji2bAAAABGdBTUEAALGPC/xhBQAAAOVJREFUOBGtVMENwzAIjKP++2026ETdpv10iy7WFbqFyyW6GBywLCv5gI+Dw2Bluj1znuSjhb99Gkn6QILDY2imo60p8nsnc9bEo3+QJ+AKHfMdZHnl78wyTnyHZD53Zzx73MRSgYvnqgCUHj6gwdck7Zsp1VOrz0Uz8NbKunzAW+Gu4fYW28bUYutYlzSa7B84Fh7d1kjLwhcSdYAYrdkMQVpsBr5XgDGuXwQfQr0y9zwLda+DUYXLaGKdd2ZTtvbolaO87pdo24hP7ov16N0zArH1ur3iwJpXxm+v7oAJNR4JEP8DoAuSFEkYH7cAAAAASUVORK5CYII=',
      callback: () => {
        lf.extension.selectionSelect.openSelectionSelect()
        lf.once('selection:selected', () => {
          lf.extension.selectionSelect.closeSelectionSelect()
        })
      }
    },
    {
      type: 'image-one',
      text: '地调一平面',
      label: '地调一平面',
      className: 'icon',
      icon: new URL(`/src/assets/images/1.png`, import.meta.url).href
    },
    {
      type: 'image-two',
      text: '一平面路由器',
      label: '一平面路由器',
      className: 'icon',
      icon: new URL(`/src/assets/images/2.png`, import.meta.url).href
    },
    {
      type: 'image-three',
      text: '一平面一区纵向',
      label: '一平面一区纵向',
      className: 'icon',
      icon: new URL(`/src/assets/images/3.png`, import.meta.url).href
    },
    {
      type: 'image-four',
      text: '一平面一区交换机',
      label: '一平面一区交换机',
      className: 'icon',
      icon: new URL(`/src/assets/images/4.png`, import.meta.url).href
    }
  ])
  registerCustomElement(lf)
  lf.render(data)
})
</script>
<script setup lang="ts">
import { LogicFlow } from '@logicflow/core'
import '@logicflow/core/dist/style/index.css'
import { Control, Menu, DndPanel, SelectionSelect, Snapshot } from '@logicflow/extension'
import '@logicflow/extension/lib/style/index.css'
LogicFlow.use(DndPanel)
import { onMounted } from 'vue'
import one from './node/one'
import two from './node/two'
import three from './node/three'
import four from './node/four'
import five from './node/five'
import six from './node/six'
const registerCustomElement = (lf) => {
  lf.register(one)
  lf.register(two)
  lf.register(three)
  lf.register(four)
  lf.register(five)
  lf.register(six)
}

const data = {
  // 节点
  nodes: [
    {
      id: 1,
      type: 'image-one',
      x: 300,
      y: 200,
      text: '地调一平面'
    },
    {
      id: 2,
      type: 'image-two',
      x: 300,
      y: 300,
      text: '一平面路由器'
    },
    {
      id: 3,
      type: 'image-three',
      x: 500,
      y: 600,
      text: '一平面一区纵向'
    },
    {
      id: 4,
      type: 'image-four',
      x: 300,
      y: 600,
      text: '一平面一区交换机'
    }
  ],
  // 边
  edges: [
    {
      type: 'polyline',
      sourceNodeId: 1,
      targetNodeId: 2
    }
  ]
}
onMounted(() => {
  const lf = new LogicFlow({
    container: document.querySelector('#container') as HTMLElement,
    width: 1300,
    height: 900,
    grid: true
  })
  lf.extension.dndPanel.setPatternItems([
    {
      label: '选区',
      icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAAH6ji2bAAAABGdBTUEAALGPC/xhBQAAAOVJREFUOBGtVMENwzAIjKP++2026ETdpv10iy7WFbqFyyW6GBywLCv5gI+Dw2Bluj1znuSjhb99Gkn6QILDY2imo60p8nsnc9bEo3+QJ+AKHfMdZHnl78wyTnyHZD53Zzx73MRSgYvnqgCUHj6gwdck7Zsp1VOrz0Uz8NbKunzAW+Gu4fYW28bUYutYlzSa7B84Fh7d1kjLwhcSdYAYrdkMQVpsBr5XgDGuXwQfQr0y9zwLda+DUYXLaGKdd2ZTtvbolaO87pdo24hP7ov16N0zArH1ur3iwJpXxm+v7oAJNR4JEP8DoAuSFEkYH7cAAAAASUVORK5CYII=',
      callback: () => {
        lf.extension.selectionSelect.openSelectionSelect()
        lf.once('selection:selected', () => {
          lf.extension.selectionSelect.closeSelectionSelect()
        })
      }
    },
    {
      type: 'image-one',
      text: '地调一平面',
      label: '地调一平面',
      className: 'icon',
      icon: new URL(`/src/assets/images/1.png`, import.meta.url).href
    },
    {
      type: 'image-two',
      text: '一平面路由器',
      label: '一平面路由器',
      className: 'icon',
      icon: new URL(`/src/assets/images/2.png`, import.meta.url).href
    },
    {
      type: 'image-three',
      text: '一平面一区纵向',
      label: '一平面一区纵向',
      className: 'icon',
      icon: new URL(`/src/assets/images/3.png`, import.meta.url).href
    },
    {
      type: 'image-four',
      text: '一平面一区交换机',
      label: '一平面一区交换机',
      className: 'icon',
      icon: new URL(`/src/assets/images/4.png`, import.meta.url).href
    }
  ])
  registerCustomElement(lf)
  lf.render(data)
})
</script>

Released under the MIT License.