vue3中如何使用d3.js繪制流程圖(TS語(yǔ)法)
更新時(shí)間:2023年10月17日 11:23:05 作者:是淺笑耶
這篇文章主要給大家介紹了關(guān)于vue3中如何使用d3.js繪制流程圖的相關(guān)資料,D3.js是由javaScript語(yǔ)言編寫繪圖庫(kù),其原理是通過(guò)調(diào)用一系列內(nèi)置函數(shù),生成SVG,并在網(wǎng)頁(yè)渲染,需要的朋友可以參考下
先放效果圖:
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)不一致問(wèn)題 nextTick(() => { //使用dagreD3庫(kù)來(lái)創(chuàng)建一個(gè)有向無(wú)環(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)下的名稱,開(kāi)始-結(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è)置箭頭樣式為無(wú)箭頭 }); }, ); //創(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-11vue前端框架vueuse的useScroll函數(shù)使用源碼分析
這篇文章主要為大家介紹了vueuse的useScroll函數(shù)源碼分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08vue新手入門出現(xiàn)function () { [native code]&nbs
這篇文章主要介紹了vue新手入門出現(xiàn)function () { [native code] }錯(cuò)誤的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Vue如何使用Element-ui表單發(fā)送數(shù)據(jù)與多張圖片到后端詳解
在做項(xiàng)目的時(shí)候遇到一個(gè)問(wèn)題,前端需要上傳表單到后端,表單數(shù)據(jù)包括文本內(nèi)容和圖片,這篇文章主要給大家介紹了關(guān)于Vue如何使用Element-ui表單發(fā)送數(shù)據(jù)與多張圖片到后端的相關(guān)資料,需要的朋友可以參考下2022-04-04Vue判斷數(shù)組內(nèi)是否存在某一項(xiàng)的兩種方法
這篇文章主要介紹了Vue判斷數(shù)組內(nèi)是否存在某一項(xiàng),今天給大家分享兩種方法,分別是findIndex()和 indexOf()方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07