在vue项目中使用dagre-d3流程图

tech2026-09-23  1

近期项目中使用到d3插件绘制的流程图。

首先认识下dagre。dagre是专注于有向图布局的javascript库,由于dagre 仅仅专注于图形布局,需要使用其他方案根据 dagre 的布局信息来实际渲染图形,而 dagre-d3 就是 dagre 基于 D3 的渲染方案。

使用步骤

1、下载d3及dagreD3 import dagreD3 from "dagre-d3"; import * as d3 from "d3"; 2、数据准备 流程图作为一种有向图,与树图、网络图一样,数据由节点以及两点之间的边组成。 dataSet: { nodes: [ { id: 0, label: "申请人", shape: "rect", color: "fill:#d81b13;stroke:transparent", toolText: "" }, { id: 1, label: "支撑需求填写\n销售", shape: "rect", color: "", toolText: "" }, { id: 2, label: "支撑方案填写\n一级支撑经理", shape: "rect", color: "", toolText: "" }, { id: 3, label: "评审意见填写\n客响", shape: "rect", color: "", toolText: "" }, { id: 4, label: "支撑方案和评审填写\n一级支撑经理", shape: "rect", color: "", toolText: "" }, { id: 5, label: " 已结束 ", shape: "rect", color: "", toolText: "" } ], edges: [ {id: 1, source: 0, target: 1, label: "", color: ""}, {id: 2, source: 1, target: 2, label: "", color: ""}, {id: 3, source: 2, target: 3, label: "", color: ""}, {id: 4, source: 3, target: 4, label: "", color: ""}, {id: 5, source: 4, target: 5, label: "", color: ""}, {id: 6, source: 2, target: 5, label: "", color: ""} ] }, 3、绘制流程图 // 设置节点和连线 renderGagre () { this.tooltip = this.createTooltip(); // 创建graph对象 const g = new dagreD3.graphlib.Graph(); // 设置图 g.setGraph({ rankdir: "LR", // T:top B:bottom marginx: 60, marginy: 80, edgesep: 100, ranksep: 60 }); this.dataSet.nodes.forEach((item) => { g.setNode(item.id, { // 节点标签 label: item.label, // 节点形状 shape: item.shape, toolText: item.toolText, // 节点样式 style: item.color ? item.color : "fill:#c0c1c3;stroke:transparent",// 根据后台数据来改变节点颜色 labelStyle: "fill:#fff;", width: 83, height: 40 }); }); this.dataSet.edges.forEach((item) => { g.setEdge(item.source, item.target, { // 边标签 label: item.label, arrowheadStyle: item.color ? item.color : "fill:#c0c1c3;", // 根据后台数据来改变连线箭头的颜色 // 边样式 style: item.color ? item.color : "fill:#ffffff;stroke:#c0c1c3;stroke-width:1.5px" // 根据后台数据来改变连线的颜色 }); }); // 创建渲染器 const render = new dagreD3.render(); // 选择svg并添加一个g元素作为绘图容器 const svgGroup = d3.select('svg').append("g"); // 建立拖拽缩放 const svg = d3.select("svg"); const zoom = d3.zoom().on("zoom", function () { svgGroup.attr("transform", d3.event.transform); }); svg.call(zoom); // 在绘图容器上运行渲染器生成流程图 render(svgGroup, g); // 鼠标悬停显示隐藏tooptip svgGroup .selectAll("g.node") .on("mouseover", (v) => { // 假如当前toolText为"",则不展示 if (g.node(v).toolText === "") { return; } this.tipVisible(g.node(v).toolText); }) .on("mouseout", () => { this.tipHidden(); }); },

哦,对了要想实现上面的鼠标悬停的tooltip,还需要下面的js和css

js代码 // 创建提示框 createTooltip () { return d3 .select("body") .append("div") .classed("tooltip", true) .style("opacity", 0) .style("display", "none"); }, // tooltip显示 tipVisible (textContent) { this.tooltip .transition() .duration(400) .style("opacity", 0.9) .style("display", "block"); this.tooltip .html(textContent) .style("left", `${d3.event.pageX + 15}px`) .style("top", `${d3.event.pageY + 15}px`); }, // tooltip隐藏 tipHidden () { this.tooltip .transition() .duration(400) .style("opacity", 0) .style("display", "none"); } css 代码 .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; }

以上就能实现一个结合后台数据动态渲染的流程图,在绘制流程图的时候,也遇到一些问题:

1、要根据不同的状态,展示不同颜色的节点、连线。 解决:本来绘制流程图在mouted函数中绘制就可出现,但是现在要实时根据数据来改变,所以要先获取到后台数据,然后再渲染流程图,而且获取后台数据要在mouted中就要获取到(之前在mouted绘制流程要去除,不然后续页面会出现两个流程图),不然一开始加载就来不显示。

2、tooltip 显示不出来 这个问题真的找了很久,一开始以为这个tooltip没有没有在页面上加载出来,但是当触发这个事件的时候,页面上的滚动条是有变化的,所以tooltip是已经绘制出来的,但是不知为何显示不出来。后来才找到原因,是因为我在流程图这个组件的样式标签上加上了scoped,从而影响了样式。

3、在iview 模态框组件中使用组件,节点连线渲染出错 这个问题解决可以看我这条博客使用iview的Modal组件中包含子组件,子组件加载出现问题

总结

以上就是我在项目中的例子,有关一些配置及相关的解释,大家可以参考这篇文章d3绘制流程图

最新回复(0)