前言:由于首次接觸到antv的g6流程圖這個功能肌割,比較好奇然后就淺淺的用一下垒探,其一給需要用到的小伙伴一個簡單的案例,其二特此記錄空繁。
官方大大地址
第一步:按照官方大大的示例乖乖下載即可殿衰,官方提供了兩種引入方式,如下
1. 在項目中使用 NPM 包引入(當(dāng)前pnpm和yarn也可以)
npm install --save @antv/g6
Step 1: 使用命令行在項目目錄下執(zhí)行以下命令:
npm install --save @antv/g6
Step 2: 在需要用的 G6 的 JS 文件中導(dǎo)入:
import G6 from '@antv/g6';
2. 在 HTML 中使用 CDN 引入
// version <= 3.2
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-{$version}/build/g6.js"></script>
// version >= 3.3
<script src="https://gw.alipayobjects.com/os/lib/antv/g6/{$version}/dist/g6.min.js"></script>
// version >= 4.0
<script src="https://gw.alipayobjects.com/os/lib/antv/g6/4.3.11/dist/g6.min.js"></script>
?? 注意:
- 在
{$version}
中填寫版本號盛泡,例如3.7.1
闷祥; - 最新版可以在 NPM 查看最新版本及版本號;
- 詳情參考 Github 分支:https://github.com/antvis/g6/tree/master傲诵。
const data = {
// 點集
nodes: [
{
id: 'node1', // String凯砍,該節(jié)點存在則必須,節(jié)點的唯一標(biāo)識
x: 100, // Number拴竹,可選悟衩,節(jié)點位置的 x 值
y: 200, // Number,可選栓拜,節(jié)點位置的 y 值
},
{
id: 'node2', // String座泳,該節(jié)點存在則必須惠昔,節(jié)點的唯一標(biāo)識
x: 300, // Number,可選挑势,節(jié)點位置的 x 值
y: 200, // Number镇防,可選,節(jié)點位置的 y 值
},
],
// 邊集
edges: [
{
source: 'node1', // String潮饱,必須来氧,起始點 id
target: 'node2', // String,必須香拉,目標(biāo)點 id
},
],
};
從官方提供的數(shù)據(jù)之中可以看出每一個節(jié)點都需要一個x啦扬,y,左邊來確定節(jié)點在畫布上的具體位置缕溉,顯而易見這個x考传,y坐標(biāo)對于后端開發(fā)人員根本不需要維護(hù)吃型,那我們前端如何計算出x证鸥,y坐標(biāo)而去確定位置呢,那我們肯定期望有一種工具可以自動的去計算每個節(jié)點的x勤晚,y坐標(biāo)自動在畫布上畫出來枉层,答案肯定是有的,接下來介紹我們的關(guān)鍵技術(shù)點Plugins
,它就是幫助我們自動的計算x赐写,y然后自動的畫出來鸟蜡,然后拿出我的代碼案例。
第一步:引入 g6
的同時還用引入Plugins
import G6 from '@antv/g6';
import Plugins from '@antv/g6-plugins';
第二步:處理從后端拿到的數(shù)據(jù)修改成我們可以直接使用的數(shù)據(jù)(僅供參考挺邀,這一步需要根據(jù)后端返回的數(shù)據(jù)自行調(diào)整)
useEffect(() => {
// 存儲所有節(jié)點關(guān)系
const nodes = [];
// 存儲所有節(jié)點間的指向關(guān)系
const edges = [];
tasks?.forEach(item => {
nodes.push({
shape: 'square',
label: item.taskName,
color: 'black',
id: item.id,
});
});
if (tasks?.length) {
// 添加開始節(jié)點
nodes.unshift({
shape: 'circle',
label: '開始', // 節(jié)點名稱
color: 'red', // 設(shè)置節(jié)點背景色
id: 'start', // 本節(jié)點id
});
// 添加結(jié)束節(jié)點
nodes.push({
shape: 'circle',
label: '結(jié)束', // 節(jié)點名稱
color: 'red', // 設(shè)置節(jié)點背景色
id: 'end', // 本節(jié)點id
});
// 將開始節(jié)點和節(jié)點連接起來
heads?.forEach(item => {
edges.push({
shape: 'arrow',
source: 'start',
target: item,
id: `start-${item}`,
});
});
// 將結(jié)束節(jié)點和節(jié)點連接起來
tails?.forEach(item => {
edges.push({
shape: 'arrow',
source: item,
target: 'end',
id: `${item}-end`,
});
});
}
// 將中間節(jié)點連接起來
relations?.forEach(item => {
edges.push({
shape: 'arrow',
source: item.preProcessTaskDefinitionId,
target: item.postProcessTaskDefinitionId,
id: `${item.id}`,
});
});
第三步:配置G6畫布
const dagre = new Plugins['layout.dagre']({
rankdir: 'TB',
nodesep: 50,
ranksep: 50,
});
const net = new G6.Net({
id: 'c1', // 容器ID
fitView: 'cc',
mode: 'none',
plugins: [dagre],
});
// 重中之重配置plugins就是讓x揉忘,y坐標(biāo)自動生成
第四步:載入數(shù)據(jù)
net.source(nodes, edges);
第五步:渲染關(guān)系圖
net.render();
優(yōu)化點:加入如下代碼是為了每次繪制前先清除上一次的
flowRef.current.innerHTML = '';
完整代碼:
import React, { useEffect, useRef, useMemo } from 'react';
import request from '@/request';
import { useLocation } from 'react-router-dom';
import { useRequest } from 'ahooks';
import qs from 'query-string';
import G6 from '@antv/g6';
import Plugins from '@antv/g6-plugins';
const DagProcessHistory = () => {
const { search } = useLocation();
const { id, dagBaseInfoReadOnly } = qs.parse(search);
const flowRef = useRef(null);
// 獲取詳情數(shù)據(jù)
const { data } = useRequest(() => request.viewFlowApi(id), {
refreshDeps: [id],
});
const { tasks, relations, heads, tails } = data?.data ?? {};
useEffect(() => {
// 存儲所有節(jié)點關(guān)系
const nodes = [];
// 存儲所有節(jié)點間的指向關(guān)系
const edges = [];
tasks?.forEach(item => {
nodes.push({
shape: 'square',
label: item.taskName,
color: 'black',
id: item.id,
});
});
if (tasks?.length) {
// 添加開始節(jié)點
nodes.unshift({
shape: 'circle',
label: '開始', // 節(jié)點名稱
color: 'red', // 設(shè)置節(jié)點背景色
id: 'start', // 本節(jié)點id
});
// 添加結(jié)束節(jié)點
nodes.push({
shape: 'circle',
label: '結(jié)束', // 節(jié)點名稱
color: 'red', // 設(shè)置節(jié)點背景色
id: 'end', // 本節(jié)點id
});
// 將開始節(jié)點和節(jié)點連接起來
heads?.forEach(item => {
edges.push({
shape: 'arrow',
source: 'start',
target: item,
id: `start-${item}`,
});
});
// 將結(jié)束節(jié)點和節(jié)點連接起來
tails?.forEach(item => {
edges.push({
shape: 'arrow',
source: item,
target: 'end',
id: `${item}-end`,
});
});
}
// 將中間節(jié)點連接起來
relations?.forEach(item => {
edges.push({
shape: 'arrow',
source: item.preProcessTaskDefinitionId,
target: item.postProcessTaskDefinitionId,
id: `${item.id}`,
});
});
flowRef.current.innerHTML = '';
// eslint-disable-next-line new-cap
const dagre = new Plugins['layout.dagre']({
rankdir: 'TB',
nodesep: 50,
ranksep: 50,
});
// 配置G6畫布
const net = new G6.Net({
id: 'c1', // 容器ID
fitView: 'cc',
mode: 'none',
plugins: [dagre],
});
// 載入數(shù)據(jù)
net.source(nodes, edges);
// 渲染關(guān)系圖
net.render();
}, [tasks, relations]);
return (
<div style={{ marginTop: '20px' }} id="c1" ref={flowRef} />
);
};
export default DagProcessHistory;
最終效果圖
我們的需求是需要開始節(jié)點和結(jié)束節(jié)點的所以手動將節(jié)點中加入了開始節(jié)點和結(jié)束節(jié)點,大家可以根據(jù)實際需求自行調(diào)整端铛,本篇文章僅為簡單demo和記錄泣矛。