1.首先安装d3和dagre-d3插件(因为dagre-d3基于d3实现的,所有要一起安装)
npm install d3
npm install dagre-d3
2.由于目前uniapp官方不支持svg组件,安装SVG.js。(通过SVG.js 构造svg实例)
npm install @svgdotjs/svg.js
yarn add @svgdotjs/svg.js
3.利用svg.js构造一个实例。
<template>
<scroll-view class="scroll" scroll-y scroll-x>
<view
class="content"
id="content"
:data="list"
:change:data="chart.queryList"
:style="{ height }"
>
</view>
</scroll-view>
</template>
<script>
import { SVG } from "@svgdotjs/svg.js";
export default {
methods: {
// 初始化svg容器
init() {
let draw = SVG()
.addTo("#content")
.attr({
id: "chart",
})
.size("100%", "100%");
},
},
};
</script>
4.接下来看整体demo
<template>
<scroll-view class="scroll" scroll-y scroll-x>
<view
class="content"
id="content"
:data="list"
:change:data="chart.queryList"
:style="{ height }"
>
</view>
</scroll-view>
</template>
<script>
import { getHiddenDangerId } from "@/api/trouble/ledger.js";
export default {
data() {
return {
id: "",
list: null,
height: "",
};
},
onLoad(option) {
this.id = option.id;
},
mounted() {
this.queryData(this.id);
},
methods: {
queryData(id) {
getHiddenDangerId(id).then((res) => {
this.list = res.data;
let numList = [];
for (let i = 0; i < this.list.reportApprovePoints.length; i++) {
if (numList.indexOf(this.list.reportApprovePoints[i].source) === -1) {
numList.push(this.list.reportApprovePoints[i].source);
} else {
break;
}
}
this.height =
(numList.length + 1) * 183.4 + numList.length * 45 + 100 + "px";
});
},
},
};
</script>
<script module="chart" lang="renderjs">
import dagreD3 from "dagre-d3";
import * as d3 from "d3";
import { SVG } from "@svgdotjs/svg.js";
export default {
data() {
return {
chartData: {},
};
},
methods: {
queryList(newValue, oldValue) {
if (newValue) {
let data = JSON.parse(JSON.stringify(newValue));
data.reportApproveInfos.forEach((i) => {
if (i.status == 0) {
i.color = "red";
i.statustext = "未处理";
} else if (i.status == 1) {
i.color = "#95ec69";
i.statustext = "已处理";
} else {
i.color = "rgba(48,243,165,0.66)";
i.statustext = "驳回";
}
});
data.reportApprovePoints.forEach((i) => {
if (i.ownCheck == null) {
i.ownCheck = "";
i.color = "#000";
} else if (i.ownCheck == 0) {
i.ownCheck = "自行验收";
i.color = "#D469ECFF";
}
});
this.chartData.nodeInfos = data.reportApproveInfos;
this.chartData.edges = data.reportApprovePoints;
this.draw();
}
},
draw() {
//获取D3
let g = new dagreD3.graphlib.Graph().setGraph({});
g.setGraph({
rankdir: "TB",
marginx: 50,
marginy: 50,
});
// 添加节点
this.chartData.nodeInfos.forEach((item, index) => {
item.rx = item.ry = 5; //圆角
g.setNode(item.id, {
labelType: "html",
label:
`<div>
<p style="text-align:left;margin: 7px 0;">流程:` +
item.processName +
`</p>
<p style="text-align:left;margin: 7px 0;">单位:` +
item.unitName +
`</p>
<p style="text-align:left;margin: 7px 0;">部门:` +
item.deptName +
`</p>
<p style="text-align:left;margin: 7px 0;">姓名:` +
item.userName +
`</p>
<p style="text-align:left;margin: 7px 0;">状态:` +
item.statustext +
`</p>
<p style="text-align:left;margin: 7px 0;">时间:` +
item.updateTime +
`</p>
<el-tooltip placement="top-start" content=` +
item.approvalOpinions +
` effect="dark"><p class ="pTitle">
意见:` +
item.approvalOpinions +
`</p>
</el-tooltip></div>`,
style: "fill:" + item.color + ";stroke:" + item.color,
width: 160,
height: 160,
});
});
// 链接关系
this.chartData.edges.forEach((item) => {
g.setEdge(item.source, item.target, {
label: item.ownCheck,
labelStyle: "fill:" + item.color,
});
});
//绘制图形
let draw = SVG()
.addTo("#content")
.attr({
id: "chart",
})
.size("100%", "100%");
this.$nextTick(() => {
let svg = d3.select("svg");
let render = new dagreD3.render();
render(svg, g);
});
},
},
};
</script>
<style lang="scss">
.scroll {
height: 100vh;
white-space: nowrap;
width: 100vw;
}
.pTitle {
text-overflow: ellipsis;
margin: 7px 0;
width: 160px;
overflow: hidden;
white-space: nowrap;
}
#content {
width: 510px;
height: 100%;
display: flex;
align-items: center;
}
svg {
font-size: 14px;
}
.node rect {
stroke: #606266;
fill: #fff;
}
.edgePath path {
stroke: #606266;
fill: #333;
stroke-width: 1.5px;
}
.tooltip {
position: absolute;
font-size: 12px;
text-align: center;
background-color: white;
border-radius: 3px;
box-shadow: rgb(174, 174, 174) 0px 0px 10px;
cursor: pointer;
display: inline-block;
padding: 10px;
}
.tooltip > div {
padding: 10px;
}
</style>