activiti5.21 + SVG 绘制流程图 高亮显示已完成节点

本功能实现是结合actitivi5.21的数据结构来获取相关数据,并通过AJAX调用进行SVG图形的绘制。

1、SpringBoot 接口及相关实体

/**
 * 读取组装绘制流程图的数据
 */
@RequestMapping(value = "/getDrawingFlowChart/{processInstanceId}")
@ResponseBody
public ImgJSON getDrawingFlowChart(HttpServletResponse response,@PathVariable String processInstanceId){
    //获取历史流程实例
    HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();

    //获取流程图
    BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
    List<BmpNodeInfo> bmpNodeInfos=new ArrayList<BmpNodeInfo>();
    if(bpmnModel!=null){
        List<FlowElement> flowElements= (List<FlowElement>) bpmnModel.getProcesses().get(0).getFlowElements();
        for(int i=0;i<flowElements.size();i++){
            BmpNodeInfo bmpNodeInfo=new BmpNodeInfo();
            bmpNodeInfo.setClassType(flowElements.get(i).getClass().getName());
            bmpNodeInfo.setId(flowElements.get(i).getId());
            bmpNodeInfo.setName(flowElements.get(i).getName());
            bmpNodeInfos.add(bmpNodeInfo);
        }
    }
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    processEngineConfiguration = processEngine.getProcessEngineConfiguration();
    Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);

    ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
    ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId());

    List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
    //高亮环节id集合
    List<String> highLightedActivitis = new ArrayList<String>();
    //高亮线路id集合
    List<String> highLightedFlows = DrawingFlowChartUtil.getHighLightedFlows(definitionEntity, highLightedActivitList);

    for (HistoricActivityInstance tempActivity : highLightedActivitList) {
        String activityId = tempActivity.getActivityId();
        highLightedActivitis.add(activityId);
    }
    ImgJSON imgJSON=new ImgJSON();
    imgJSON.setBpmnModel(bpmnModel);
    imgJSON.setHighLightedActivitList(highLightedActivitList);
    imgJSON.setHighLightedActivitis(highLightedActivitis);
    imgJSON.setHighLightedFlows(highLightedFlows);
    imgJSON.setList(bmpNodeInfos);
    return imgJSON;
}
public class BmpNodeInfo {
    private String classType;
    private String id;
    private String name;

    public String getClassType() {
        return classType;
    }

    public void setClassType(String classType) {
        this.classType = classType;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.history.HistoricActivityInstance;

import java.io.Serializable;
import java.util.List;

public class ImgJSON implements Serializable {
    private BpmnModel bpmnModel;
    private List<HistoricActivityInstance> highLightedActivitList;
    private List<String> highLightedActivitis;
    private List<String> highLightedFlows;
    private List<BmpNodeInfo> list;


    public BpmnModel getBpmnModel() {
        return bpmnModel;
    }

    public void setBpmnModel(BpmnModel bpmnModel) {
        this.bpmnModel = bpmnModel;
    }

    public List<HistoricActivityInstance> getHighLightedActivitList() {
        return highLightedActivitList;
    }

    public void setHighLightedActivitList(List<HistoricActivityInstance> highLightedActivitList) {
        this.highLightedActivitList = highLightedActivitList;
    }

    public List<String> getHighLightedActivitis() {
        return highLightedActivitis;
    }

    public void setHighLightedActivitis(List<String> highLightedActivitis) {
        this.highLightedActivitis = highLightedActivitis;
    }

    public List<String> getHighLightedFlows() {
        return highLightedFlows;
    }

    public void setHighLightedFlows(List<String> highLightedFlows) {
        this.highLightedFlows = highLightedFlows;
    }

    public List<BmpNodeInfo> getList() {
        return list;
    }

    public void setList(List<BmpNodeInfo> list) {
        this.list = list;
    }
}

2、JS文件


function createRects(rects,list,hights,draw) {
    $.each(rects,function (key,values) {
        var nodeType=getNodeType(key,list);
        if(nodeType!=null && nodeType!=""){
            if(nodeType[0]=="StartEvent" || nodeType[0]=="EndEvent"){
                draw.appendChild(createCircle(values.x+values.width/2,values.y+values.width/2,values.width/2,getNodeHightLighte(key,hights),nodeType[1],nodeType[0]));
            }else if(nodeType[0]=="InclusiveGateway" ||nodeType[0]==" ExclusvieGateway" ||nodeType[0]=="EventGateway" ||nodeType[0]=="ParallelGateway"){
                draw.appendChild(createDoublePolygon(values.x,values.y,values.width,values.height,getNodeHightLighte(key,hights),nodeType[1]));
            }else{
                draw.appendChild(createRect(values.x,values.y,values.width,values.height,getNodeHightLighte(key,hights),nodeType[1]));
            }
        }

    });
}
//判断节点是否需要高亮显示
function getNodeHightLighte(key,hights) {
    var boo=false;
    $.each(hights,function (index,item) {
        if(key==item){
            boo=true;
        }
    });
    return boo;
}
//查找节点的类型
function getNodeType(key,list) {
    var name={};
    var re=new Array();
    $.each(list,function (index,item) {
        if(key==item.id){
            name= item.classType.split(".");
            re[1]=item.name;
        }
    });
    if(name!=null && name.length>0){
        re[0]=name[name.length-1];

    }
    return re;

}
function createDoublePolygon(x,y,width,height,hl) {
    var g=document.createElementNS("http://www.w3.org/2000/svg","g");
    g.appendChild(createPolygon(x,y,width,height,hl));
    g.appendChild(createPolygon(x+width/4,y+height/4,width/2,height/2,hl));
    return g;
}
//画一个棱形
function createPolygon (x,y,width,height,hl) {
    var node;

    node=document.createElementNS("http://www.w3.org/2000/svg","polygon");
    var point=(x+width/2)+","+y;
    point=point+" "+(x+width)+","+(y+height/2);
    point=point+" "+(x+width/2)+","+(y+height);
    point=point+" "+x+","+(y+height/2);
    node.setAttribute("points",point);
    node.setAttribute("fill","#FFFFFF");
    if(hl==true){
        node.setAttribute("stroke","#1ccb6f");
    }else{
        node.setAttribute("stroke","#000000");
    }
    node.setAttribute("stroke-width","2");

    return node;
}
//画一个圆
function createCircle(x,y,r,hl,text_str,nodetype) {
    var node;
    var g=document.createElementNS("http://www.w3.org/2000/svg","g");
    node=document.createElementNS("http://www.w3.org/2000/svg","circle");
    var text=document.createElementNS("http://www.w3.org/2000/svg","text");
    node.setAttribute("cx",x);
    node.setAttribute("cy",y);
    node.setAttribute("r",r);
    if(hl==true){
        node.setAttribute("stroke","#1ccb6f");
    }else{
        node.setAttribute("stroke","#000000");
    }
    node.setAttribute("stroke-width","2");
    node.setAttribute("fill","#FFFFFF");
    text.setAttribute("text-anchor","middle");
    text.style.fontSize="0.5em";
    text.textContent=text_str;
    text.setAttribute("startOffset","1");
    text.setAttribute("x",x);
    if(nodetype=="StartEvent"){
        text.setAttribute("y",y-r-10);
    }else{
        text.setAttribute("y",y+r+10);
    }

    text.setAttribute("fill","black");
    g.appendChild(node);
    g.appendChild(text);
    return g;
}
// 画一个矩形
function createRect(x,y,width,height,hl,text_str) {
    var node;
    var g=document.createElementNS("http://www.w3.org/2000/svg","g");
    var text=document.createElementNS("http://www.w3.org/2000/svg","text");
    // <foreignObject width="120" height="50">
    //         <body xmlns="http://www.w3.org/1999/xhtml">
    //         <p style="font-size:12px;margin:0;">一段需要word wrap的文字。</p>
    //     </body>
    //     </foreignObject>
    g.setAttribute("type","userTask");
    // g.setAttribute("id","id_"+v.id);
    node=document.createElementNS("http://www.w3.org/2000/svg","rect");
    node.setAttribute("x",x);//矩形的左侧位置
    node.setAttribute("y",y);//矩形的顶部位置
    node.setAttribute("rx","5");//圆角
    node.setAttribute("ry","5");//圆角
    node.setAttribute("height",height);//矩形的高度
    node.setAttribute("width",width);//矩形的宽度
    if(hl==true){
        node.setAttribute("stroke","#1ccb6f");

    }else{
        node.setAttribute("stroke","#000000");

    }
    node.setAttribute("stroke-width","2");
    node.setAttribute("fill","#FFFFFF");
    text.setAttribute("text-anchor","middle");
    text.setAttribute("height",height);//矩形的高度
    text.setAttribute("width",width);//矩形的宽度
    // var body=document.createElementNS("http://www.w3.org/2000/svg","body");
    // body.setAttribute("xmlns","http://www.w3.org/1999/xhtml");
    // var p=document.createElementNS("http://www.w3.org/2000/svg","p");
    // // p.css({"font-size":"12px","margin":"0"});
    // p.textContent=text_str;
    // body.appendChild(p);
    // text.appendChild(body);
    text.style.fontSize="0.7em";
    text.textContent=text_str;
    text.setAttribute("startOffset","1");
    text.setAttribute("x",x+width/2);
    text.setAttribute("y",y+height-10);
    //
    // node.appendChild(text);
    g.appendChild(node);
    g.appendChild(text);
    return g;
}
function createLines(lines,hight,drwa) {
    $.each(lines,function (key,item) {
        if(item.length>2){
            var points=new Array();
            var j=0;
            for(var i=0;i<item.length;i++){
                var pp=new Array();
                pp[0]=item[i].x;
                pp[1]=item[i].y;
                points[j++]=pp;
            }
            draw.appendChild( createBrokenLine(points,getNodeHightLighte(key,hight)));
        }else{
            draw.appendChild( createLine(item[0].x,item[0].y,item[1].x,item[1].y,getNodeHightLighte(key,hight)));
        }
    });
}
function createLine(x1,y1,x2,y2,hl) {
    var node;
    var g=document.createElementNS("http://www.w3.org/2000/svg","g");
    // var text=document.createElementNS("http://www.w3.org/2000/svg","text");
    g.setAttribute("type","userTask");
    // g.setAttribute("id","id_"+v.id);
    node=document.createElementNS("http://www.w3.org/2000/svg","path");
    node.setAttribute("fill","none");
    if(hl==true){
        node.setAttribute("stroke","#1ccb6f");
    }else{
        node.setAttribute("stroke","#000000");//线颜色
    }

    // text.setAttribute("startOffset","1");
    // text.setAttribute("x",parseInt(node.getAttribute("x"))+parseInt(node.getAttribute("width"))/2);
    // text.setAttribute("y",parseInt(node.getAttribute("y"))+parseInt(node.getAttribute("height"))/2);
    // text.setAttribute("fill","black");
    node.setAttribute("d",drawLineArrow(x1,y1,x2,y2));
    g.appendChild(node);
    // g.appendChild(text);
    return g;
}
function createBrokenLine(points,hl) {
    var node;
    var g=document.createElementNS("http://www.w3.org/2000/svg","g");
    // var text=document.createElementNS("http://www.w3.org/2000/svg","text");
    g.setAttribute("type","userTask");
    // g.setAttribute("id","id_"+v.id);
    node=document.createElementNS("http://www.w3.org/2000/svg","path");
    node.setAttribute("fill","none");
    if(hl==true){
        node.setAttribute("stroke","#1ccb6f");
    }else{
        node.setAttribute("stroke","#000000");//线颜色
    }

    // text.setAttribute("startOffset","1");
    // text.setAttribute("x",parseInt(node.getAttribute("x"))+parseInt(node.getAttribute("width"))/2);
    // text.setAttribute("y",parseInt(node.getAttribute("y"))+parseInt(node.getAttribute("height"))/2);
    // text.setAttribute("fill","black");
    node.setAttribute("d",drawBrokenLineArrow(points));
    g.appendChild(node);
    // g.appendChild(text);
    return g;
}
// 画折线和箭头
function drawBrokenLineArrow(points) {
    var path = "";
    for (var i = 0; i <= points.length - 2; i++) {
        var p = points[i];
        var p2 = points[i + 1];
        if (i == points.length - 2) {
            path += drawLineArrow(p[0], p[1], p2[0], p2[1]);
        } else {
            path += "M" + p[0] + "," + p[1] + " L" + p2[0] + "," + p2[1];
        }
    }

    console.log("BrokenLine, path=" + path);

    return path;
}
// 画直线和箭头
function drawLineArrow(x1, y1, x2, y2) {
    var path;
    var slopy, cosy, siny;
    var Par = 10.0;
    var x3, y3;
    slopy = Math.atan2((y1 - y2), (x1 - x2));
    cosy = Math.cos(slopy);
    siny = Math.sin(slopy);

    path = "M" + x1 + "," + y1 + " L" + x2 + "," + y2;

    x3 = x2;
    y3 = y2;

    path += " M" + x3 + "," + y3;
    path += " L" + (Number(x3) + Number(Par * cosy - (Par / 2.0 * siny))) + "," + (Number(y3) + Number(Par * siny + (Par / 2.0 * cosy)));
    path += " M" + (Number(x3) + Number(Par * cosy + Par / 2.0 * siny) + "," + (Number(y3) - Number(Par / 2.0 * cosy - Par * siny)));
    path += " L" + x3 + "," + y3;

    console.log("path=" + path);
    return path;
}
function moveMouse(even) {
    var rects=document.getElementsByTagName("rect");
    $.each(rects,function (index,item) {
        $(item).on('click',function (event) {
            alert("Ss");
        });
    })

}

3、HTML调用

<!DOCTYPE html>
<html  lang="zh" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
    <script type="application/javascript" th:src="@{/my_js/jquery2.1.4.js}"></script>
    <script type="application/javascript" th:src="@{/bootstrap-3.3.7-dist/js/bootstrap.js}"></script>
    <script type="application/javascript" th:src="@{/my_js/activiti_svg.js}"></script>

<script type="application/javascript">
    /*<![CDATA[*/
    var draw_width=800//$(window).width();//初始画布大小为浏览器可视区域大小
    var draw_height=500//$(window).height();//初始画布大小为浏览器可视区域大小
    var draw = document.createElementNS("http://www.w3.org/2000/svg","svg");

    $(draw).css({"width":draw_width+"px","height":draw_height+"px","border":"1px sold #000000"});

    $(function () {
        getImgJson();

    });
    function getImgJson() {
        $.ajax({
            url:'/getDrawingFlowChart/122663',
            type:'GET', //GET
            async : true,
            data:{
            },
            timeout:10000,    //超时时间
            dataType:'json',    //返回的数据格式:
            success:function(json){
                createRects(json.bpmnModel.locationMap,json.list,json.highLightedActivitis,draw);
                createLines(json.bpmnModel.flowLocationMap,json.highLightedFlows);
                $('#svg_c').html(draw);
                console.log(json);
            },
            error:function(xhr,textStatus){
                console.log('错误')
                console.log(xhr)
                console.log(textStatus)
            }
        });
    }

    /*]]>*/
</script>

</head>
<body >

<div id="svg_c">
</div>
</body>
</html>

4、示例(任意拖拉流程)   bpm文件效果

html 绘制效果

大家有时间可以将折线绘制了好看点,对点进行计算形成四个点的折线会更加好看

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值