vue3中如何使用d3.js繪制流程圖(TS語法)
更新時(shí)間:2023年10月17日 11:23:05 作者:是淺笑耶
這篇文章主要給大家介紹了關(guān)于vue3中如何使用d3.js繪制流程圖的相關(guān)資料,D3.js是由javaScript語言編寫繪圖庫,其原理是通過調(diào)用一系列內(nèi)置函數(shù),生成SVG,并在網(wǎng)頁渲染,需要的朋友可以參考下
先放效果圖:

1.安裝dagre-d3和d3:
npm install d3 npm install dagre-d3
2.在組件中導(dǎo)入并使用d3和dagre-d3:
<script>
import * as d3 from 'd3';
import dagreD3 from 'dagre-d3';
</script>3.在模板中創(chuàng)建節(jié)點(diǎn)元素:
<template>
<div class="top_model">
<div class="flow_chart" ref="flowchartContainer"></div>
</div>
</template>4.在setup中定義所需數(shù)據(jù):
setup() {
//創(chuàng)建一個(gè)ref引用對(duì)象,它用于引用以上綁定ref為flowchartContainer的DOM元素
const flowchartContainer = ref(null);
const taskLogData = reactive({
dataSource: [] as any,
//流程圖數(shù)據(jù)
list: {
nodeInfos: [] as any,
edges: [] as any,
},
})
}5.進(jìn)行繪制:
//mounted生命周期鉤子函數(shù)是在組件實(shí)例掛載到 DOM 后調(diào)用的,
//在這個(gè)時(shí)候可以獲取到組件的根元素,并且可以執(zhí)行相應(yīng)的操作
//因此將繪制代碼放在這里執(zhí)行
onMounted(async () => {
//調(diào)用了接口getListData,需要從其中取出數(shù)據(jù),因此需要執(zhí)行異步方法async/await
await getListData();
//nextTick函數(shù)確保了在DOM更新之后再執(zhí)行相應(yīng)的操作,
//避免了由于異步更新導(dǎo)致的狀態(tài)不一致問題
nextTick(() => {
//使用dagreD3庫來創(chuàng)建一個(gè)有向無環(huán)圖的圖形
var g = new dagreD3.graphlib.Graph().setGraph({
rankdir: 'LR', // 指定布局方向?yàn)閺淖蟮接?
nodesep: 200, // 設(shè)置節(jié)點(diǎn)間距
ranksep: 250, //垂直間距
});
//添加節(jié)點(diǎn)
taskLogData.list.nodeInfos.forEach(
(
item: {
id: string;
label: any;
tooltip: any;
tipone: any;
tiptow: any;
tipthree: any;
color: any;
},
index: any,
) => {
//設(shè)置圖形中指定節(jié)點(diǎn)的屬性
g.setNode(item.id, {
label: item.label,//節(jié)點(diǎn)內(nèi)容
//自定義屬性,調(diào)整樣式使其成為節(jié)點(diǎn)備注
tooltip: item.tooltip,//節(jié)點(diǎn)備注(對(duì)應(yīng)圖片中的節(jié)點(diǎn)下的名稱,開始-結(jié)束)
tipone: item.tipone,//節(jié)點(diǎn)備注1(對(duì)應(yīng)圖片中的時(shí)間)
tiptow: item.tiptow,//節(jié)點(diǎn)備注2(對(duì)應(yīng)圖片中的操作人員)
tipthree: item.tipthree,//節(jié)點(diǎn)備注3(對(duì)應(yīng)圖片中的藍(lán)色備注)
style: `fill: ${item.color}`,//節(jié)點(diǎn)填充顏色,item.color為變量
shape: 'circle',//節(jié)點(diǎn)形狀設(shè)置為圓形
class: 'node',//設(shè)置節(jié)點(diǎn)類名
rank: 0, // 設(shè)置節(jié)點(diǎn)的rank屬性為0,表示在同一水平排列
});
},
);
//添加節(jié)點(diǎn)關(guān)系
taskLogData.list.edges.forEach(
(item: { source: string; target: string; edgeColor: string }) => {
//創(chuàng)建并設(shè)置圖形中兩個(gè)節(jié)點(diǎn)之間的邊(Edge)
g.setEdge(item.source, item.target, {
// 設(shè)置邊的樣式
style: 'stroke: ' + item.edgeColor + ';
fill: none; stroke-width: 2px;',
arrowheadStyle: 'fill: none;', // 設(shè)置箭頭樣式為無箭頭
});
},
);
//創(chuàng)建一個(gè)SVG元素作為繪圖容器,
//并將其添加到flowchartContainer.value所引用的DOM元素中
const svg = d3
.select(flowchartContainer.value)
//在選定的DOM元素內(nèi)添加一個(gè)SVG元素
.append('svg')
//設(shè)置SVG元素的寬度與高度屬性
.attr('width', '')
.attr('height', 240);
// 創(chuàng)建渲染器
const render = new dagreD3.render();
// 執(zhí)行渲染
render(svg as any, g as any);
// 添加節(jié)點(diǎn)備注
//獲取并遍歷類名為node的元素
svg.selectAll('.node').each((nodeId, index) => {
// 獲取節(jié)點(diǎn)的備注信息
const tooltipText = g.node(nodeId as any).tooltip;
const tipone = g.node(nodeId as any).tipone;
const tiptow = g.node(nodeId as any).tiptow;
const tipthree = g.node(nodeId as any).tipthree;
//獲取節(jié)點(diǎn)對(duì)象
const node = d3.select(flowchartContainer.value);
// 獲取元素的位置
const bbox = g.node(nodeId as any);
// 在節(jié)點(diǎn)下方添加備注文本
const remarkText = (node as any)
.append('text')
.attr('class', 'node-remark')
.text(tooltipText);
const remarkTextone = (node as any)
.append('text')
.attr('class', 'node-remark')
.text(tipone);
const remarkTexttow = (node as any)
.append('text')
.attr('class', 'node-remark')
.text(tiptow);
const remarkTextthree = (node as any)
.append('text')
.attr('class', 'node-remark')
.text(tipthree)
.attr('class', 'remarkLast')
.attr('id', 'remarkLast' + nodeId);
//添加氣泡彈窗
const remarkTextFour = (node as any)
.append('div')
.attr('class', 'remarkFlow')
.attr('id', 'remarkFlow' + nodeId)
.text(tipthree);
// 調(diào)整備注位置
remarkText
.style('position', 'absolute')
.style('top', `${bbox.y + 60}px`)
.style('left', `${bbox.x + 30}px`);
remarkTextone
.style('position', 'absolute')
.style('top', `${bbox.y + 80}px`)
.style('left', `${bbox.x + 30}px`);
remarkTexttow
.style('position', 'absolute')
.style('top', `${bbox.y + 100}px`)
.style('max-width', '130px')
.style('left', `${bbox.x + 30}px`);
remarkTextthree
.style('position', 'absolute')
.style('top', `${bbox.y + 130}px`)
.style('left', `${bbox.x + 30}px`);
remarkTextFour
.style('position', 'absolute')
.style('top', `${bbox.y + 60}px`)
.style('left', `${bbox.x + 30}px`);
//鼠標(biāo)懸停效果
(document.getElementById('remarkLast' + nodeId) as any).onmouseover
= function () {
(document.getElementById('remarkFlow' + nodeId) as any)
.style.display = 'block';
};
(document.getElementById('remarkLast' + nodeId) as any).onmouseout
= function () {
(document.getElementById('remarkFlow' + nodeId) as any)
.style.display = 'none';
};
});
});
});6.對(duì)接口數(shù)據(jù)進(jìn)行處理:
// 獲取流程圖數(shù)據(jù)
const getListData = async () => {
const res: any = await getTaskLogs();
console.log('res', res);
if (res.status_code == '0000') {
const nodeList= res.data;
// 打印數(shù)組中的節(jié)點(diǎn)
console.log('節(jié)點(diǎn):', nodeList);
for (var i = 0; i < nodeList.length; i++) {
//默認(rèn)節(jié)點(diǎn)連線顏色為綠色
let edgeColor = '#52c41a';
//當(dāng)前節(jié)點(diǎn)之后的節(jié)點(diǎn)都設(shè)為灰色
for (var j = i - 1; j > 0; j--) {
if (nodeList[j].isCurNode == true) {
taskLogData.list.nodeInfos[i].color = '#d9d9d9';
edgeColor = '#d9d9d9';
}
}
//當(dāng)前節(jié)點(diǎn)設(shè)為藍(lán)色
if (nodeList[i].isCurNode == true) {
taskLogData.list.nodeInfos[i].color = '#1890ff';
edgeColor = '#1890ff';
}
//節(jié)點(diǎn)之間的連線
if (i > 0) {
taskLogData.list.edges.push({
source: nodeList[i - 1].nodeId,
target: nodeList[i].nodeId,
edgeColor: edgeColor,
style: 'stroke-solid',
});
}
}
} else {
message.error(res.reason);
}
};總結(jié)
到此這篇關(guān)于vue3中如何使用d3.js繪制流程圖的文章就介紹到這了,更多相關(guān)vue3用d3.js繪制流程圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
el-form-item表單label添加提示圖標(biāo)的實(shí)現(xiàn)
本文主要介紹了el-form-item表單label添加提示圖標(biāo)的實(shí)現(xiàn),我們將了解El-Form-Item的基本概念和用法,及添加提示圖標(biāo)以及如何自定義圖標(biāo)樣式,感興趣的可以了解一下2023-11-11
vue前端框架vueuse的useScroll函數(shù)使用源碼分析
這篇文章主要為大家介紹了vueuse的useScroll函數(shù)源碼分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
vue新手入門出現(xiàn)function () { [native code]&nbs
這篇文章主要介紹了vue新手入門出現(xiàn)function () { [native code] }錯(cuò)誤的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
Vue如何使用Element-ui表單發(fā)送數(shù)據(jù)與多張圖片到后端詳解
在做項(xiàng)目的時(shí)候遇到一個(gè)問題,前端需要上傳表單到后端,表單數(shù)據(jù)包括文本內(nèi)容和圖片,這篇文章主要給大家介紹了關(guān)于Vue如何使用Element-ui表單發(fā)送數(shù)據(jù)與多張圖片到后端的相關(guān)資料,需要的朋友可以參考下2022-04-04
Vue判斷數(shù)組內(nèi)是否存在某一項(xiàng)的兩種方法
這篇文章主要介紹了Vue判斷數(shù)組內(nèi)是否存在某一項(xiàng),今天給大家分享兩種方法,分別是findIndex()和 indexOf()方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07

