前端使用dagre-d3生成流程图的那些事儿

这两天遇到这样一个需求,在前端页面展示流程图,我之前没有做过类似的需求,就来找万能的度娘 了。流程图根据需求不同,展示的形式有所不同,但是本质还是一致的。经过百度搜索,我找到了几种方案,简单给大家介绍一下:

1.做能拖拽和编辑的流程图

推荐使用https://jsplumbtoolkit.com/demos.html,这个网站专门用于生成流程图,基本能满足你的所有需求

2.展示流程图,不对流程图做任何操作

      (1)在html页面中使用dagre-d3,生成展示型流程图

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        g.type-current>rect {
            fill: #1E9FFF;
        }

        g.type-success>rect {
            fill: green;
        }

        g.type-fail>rect {
            fill: red;
        }

        text {
            font-weight: 300;
            font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
            font-size: 14px;
        }

        .node rect {
            stroke: #999;
            fill: #fff;
            stroke-width: 1.5px;
        }

        .edgePath path {
            stroke: #333;
            stroke-width: 1.5px;
        }
    </style>
</head>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="http://cpettitt.github.io/project/dagre-d3/v0.3.0/dagre-d3.min.js"></script>
<script src=" http://d3js.org/d3.v3.min.js "></script>

<body>
    <svg id="svg-canvas" width=700 height=300></svg>
</body>
<script>

    var dataFlow = [{
        id: 0,
        label: '事项受理',
        status: 'success',
        target: 1,
        back_target:null
    },{
        id: 1,
        label: '初审',
        status: 'success',
        target: 2,
        back_target:null
    },{
        id: 2,
        label: '初审回复',
        status: 'success',
        target: 3,
        back_target:null
    },{
        id: 3,
        label: '事情打回',
        status: 'fail',
        target: 4,
        back_target: 1
    },{
        id: 4,
        label: '事项办结',
        status: 'current',
        target: null,
        back_target:null
    },{
        id: 5,
        label: '候审补正',
        status: 'done',
        target: null,
        back_target:null
    }]
    // Create the input graph
    var g = new dagreD3.graphlib.Graph()
        .setGraph({})
        .setDefaultEdgeLabel(function () { return {}; });

    dataFlow && dataFlow.map((item, i) =>{
        g.setNode(item.id, {
            label: item.label,
            class: "type-" + item.status,
            // id: "status" + i
        });
         // Set up edges, no special attributes.
        if(item.target && !item.back_target) {
            g.setEdge(item.id,item.target, {})
        }else if(item.back_target) {
            console.log(1111111)
            g.setEdge(item.id,item.target, {})
            g.setEdge(item.id,item.back_target, {})
        }
    })
  
    g.nodes().forEach(function (v) {
        var node = g.node(v);
        // Round the corners of the nodes
        node.rx = node.ry = 5;
    });

    // Create the renderer
    var render = new dagreD3.render();

    // Set up an SVG group so that we can translate the final graph.
    var svg = d3.select("svg"),
        svgGroup = svg.append("g");

    // Run the renderer. This is what draws the final graph.
    render(d3.select("svg g"), g);

    var xCenterOffset = (svg.attr("width") - g.graph().width) / 2;
    svgGroup.attr("transform", "translate(" + xCenterOffset + ", 20)");
    svg.attr("height", g.graph().height + 40);
</script>

</html>

  在html文件中,通过改变节点的class名来显示不同的颜色,展示流程到达的节点

(2)在react项目中使用 dagre-d3生成流程图

   在html文件中国我们可以直接通过script标签引入d3,dagre-d3的代码文件,但是在react项目中,我们就不能这样直接引入了,首先要先安装d3,dagre-d3的依赖包,css文件也要单独引入

import React, { Component } from 'react';
import * as d3 from 'd3';
import './Demo.css';
import * as dagreD3 from 'dagre-d3';

class Demo extends Component {
    constructor(props) {
        super(props);
        this.state = {
            dataFlow: [{
                id: 0,
                label: '事项受理',
                status: 'success',
                target: 1,
                back_target: null
            }, {
                id: 1,
                label: '初审',
                status: 'success',
                target: [3],
                back_target: null
            }, {
                id: 2,
                label: '初审回复',
                status: 'success',
                target: 3,
                back_target: null
            }, {
                id: 3,
                label: '事情打回',
                status: 'fail',
                target: 4,
                back_target: 1
            }, {
                id: 4,
                label: '事项办结',
                status: 'current',
                target: null,
                back_target: null
            }, {
                id: 5,
                label: '候审补正',
                status: 'done',
                target: null,
                back_target: null
            }]
        }
    }

    componentDidMount() {
        this.renderDag();     
    }

    renderDag() {
        const { dataFlow } = this.state;
        // // Create the input graph
        var g = new dagreD3.graphlib.Graph()
            .setGraph({})
            .setDefaultEdgeLabel(function () { return {}; });

        dataFlow && dataFlow.map((item, i) => {
            g.setNode(item.id, {
                label: item.label,
                class: "type-" + item.status,
            });
            if (item.target && !item.back_target) {
                    g.setEdge(item.id, item.target, {})
            } else if (item.back_target) {
                g.setEdge(item.id,item.target, {})
                g.setEdge(item.id,item.back_target, {})
            }
        })

        g.nodes().forEach(function (v) {
            var node = g.node(v);
            // Round the corners of the nodes
            node.rx = node.ry = 5;
        });

        // // Create the renderer
        var render = new dagreD3.render();

        // // Set up an SVG group so that we can translate the final graph.
        var svg = d3.select("svg"),
            svgGroup = svg.append("g");

        // // Run the renderer. This is what draws the final graph.
        render(d3.select("svg g"), g);
        console.log(svg,'111', svgGroup)
        var xCenterOffset = (svg.attr("width") - g.graph().width) / 2;
        svgGroup.attr("transform", "translate(" + xCenterOffset + ", 20)");
        svg.attr("height", g.graph().height + 40);
    }
    //获取dom节点
    setNodeTree = (nodeTree) => {
        this.nodeTree = nodeTree;
        this.nodeTree.background = "yellow";
    }
    //获取dom节点
    setNodeTreeInner = (nodeTreeInner) => {
        this.nodeTreeInner = nodeTreeInner;
    }

    render() {
        return (
            <svg ref={this.setNodeTree} id="svg-canvas"  width= '700px' height='300px' >
                <g ref={this.setNodeTreeInner} />
            </svg>
        )
    }
}

export default Demo;

以上就是我在工作中的一点小心得,若有错误欢迎指正,希望可以和大家多多交流,提升技术。

要自定义 Dagre-D3 流程图节点,您需要了解以下几个方面: 1. 节点数据结构:在 Dagre-D3 中,节点通常是一个 JavaScript 对象,包含一些必要的属性,如节点的 ID、宽度、高度、位置等。您可以根据您的需求来定义自己的节点数据结构。 2. 节点渲染:Dagre-D3 通过 SVG 来渲染节点。您可以使用 SVG 的各种元素(如 rect、circle、path 等)来定义您的节点外观和样式。您可以使用 Dagre-D3 提供的一些默认样式,也可以根据自己的需求来定义自己的样式。 3. 节点交互:如果您需要为节点添加交互功能,例如鼠标悬停、点击等,您可以使用 D3.js 提供的事件处理函数来实现。您可以在节点元素上绑定事件处理函数,并在函数中实现您的逻辑。 下面是一个简单的自定义节点的示例代码: ```javascript // 定义节点数据结构 var node = { id: 'node1', width: 80, height: 40, x: 100, y: 100 }; // 渲染节点 var svg = d3.select('svg'); var g = svg.append('g'); var rect = g.append('rect') .attr('width', node.width) .attr('height', node.height) .attr('x', node.x) .attr('y', node.y) .attr('fill', '#ccc'); // 添加节点交互 rect.on('mouseover', function() { d3.select(this).attr('fill', '#f00'); }).on('mouseout', function() { d3.select(this).attr('fill', '#ccc'); }); ``` 在这个示例中,我们首先定义了一个简单的节点数据结构,然后使用 SVG 的 rect 元素来渲染节点。最后,我们为 rect 元素添加了鼠标悬停和鼠标移出事件,以改变节点的填充颜色。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值