在vue项目中使用bpmn.js,显示后端获取到的xml流程图数据,对特殊步骤设置高亮颜色,流程图放大缩小功能
我遇到的问题主要是初始化时图片的尺寸很小,后来在创建canvas的时候给他一个高度就解决了,还有一个自定义高亮样色无效的问题,是因为vue中style使用了scope导致的,使用>>>解决的。其实在vue项目中大多数的ui框架修改样式无效多半是scope影响的,使用深度选择器就可以解决。
1.安装bpmn.js,运行npm install --save bpmn-js,
2.在需要使用bpmn.js的页面引入bpmn-js的组件,需要编辑就引入Modeler,如果只需要预览就引入Viewer就可以。
3.上代码,代码中对关键部分和需要注意的地方都作了注释。
<template>
<div class="main-box">
<el-button type="success"
size="small"
@click="handleZoom(0.2)">放大</el-button>
<el-button type="warning"
size="small"
@click="handleZoom(-0.2)">缩小</el-button>
<div class="canvas"
ref="canvas"></div>
</div>
</template>
<script>
// 这里只需要预览引入Viewer就可以,如果需要编辑则引入"bpmn-js/lib/Modeler",并且还需要引入左侧编辑栏panel等
import BpmnViewer from "bpmn-js/lib/Viewer";
export default {
data() {
return {
bpmnViewer: null,
scale: 1,
xmlUrl: '<?xml version="1.0" encoding="UTF-8"?>\n<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:bioc="http://bpmn.io/schema/bpmn/biocolor/1.0" id="Definitions_0niqij2" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.2.0">\n <bpmn:collaboration id="TEST1">\n <bpmn:participant id="Participant_1cvrbkh" name="测试2" processRef="TEST2" />\n </bpmn:collaboration>\n <bpmn:process id="TEST2" name="测试 2" isExecutable="true">\n <bpmn:laneSet id="LaneSet_1c6qhor">\n <bpmn:lane id="Lane_06s1mba" name="sdfsd">\n <bpmn:flowNodeRef>Activity_1d2rrr0</bpmn:flowNodeRef>\n <bpmn:flowNodeRef>StartEvent_1</bpmn:flowNodeRef>\n </bpmn:lane>\n <bpmn:lane id="Lane_103btcx" name="sdfsd">\n <bpmn:flowNodeRef>Activity_1d2wp4b</bpmn:flowNodeRef>\n <bpmn:flowNodeRef>Event_0a8jrau</bpmn:flowNodeRef>\n </bpmn:lane>\n </bpmn:laneSet>\n <bpmn:userTask id="Activity_1d2rrr0" name="ddd" camunda:formKey="form1" camunda:assignee="yang">\n <bpmn:extensionElements>\n <camunda:inputOutput>\n <camunda:inputParameter name="Input_1" />\n <camunda:outputParameter name="Output_1">aaa</camunda:outputParameter>\n </camunda:inputOutput>\n <camunda:formData>\n <camunda:formField id="id" label="iddd" type="string" defaultValue="2" />\n </camunda:formData>\n </bpmn:extensionElements>\n <bpmn:incoming>Flow_0gr7pas</bpmn:incoming>\n <bpmn:outgoing>Flow_1ayl0cy</bpmn:outgoing>\n </bpmn:userTask>\n <bpmn:startEvent id="StartEvent_1">\n <bpmn:outgoing>Flow_0gr7pas</bpmn:outgoing>\n </bpmn:startEvent>\n <bpmn:userTask id="Activity_1d2wp4b" name="dfdsfds" camunda:assignee="ddd">\n <bpmn:incoming>Flow_1ayl0cy</bpmn:incoming>\n <bpmn:outgoing>Flow_1gvp9xx</bpmn:outgoing>\n </bpmn:userTask>\n <bpmn:endEvent id="Event_0a8jrau">\n <bpmn:incoming>Flow_1gvp9xx</bpmn:incoming>\n </bpmn:endEvent>\n <bpmn:sequenceFlow id="Flow_0gr7pas" sourceRef="StartEvent_1" targetRef="Activity_1d2rrr0" />\n <bpmn:sequenceFlow id="Flow_1ayl0cy" sourceRef="Activity_1d2rrr0" targetRef="Activity_1d2wp4b" />\n <bpmn:sequenceFlow id="Flow_1gvp9xx" sourceRef="Activity_1d2wp4b" targetRef="Event_0a8jrau" />\n </bpmn:process>\n <bpmndi:BPMNDiagram id="BPMNDiagram_1">\n <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="TEST1">\n <bpmndi:BPMNShape id="Participant_1cvrbkh_di" bpmnElement="Participant_1cvrbkh" isHorizontal="true">\n <dc:Bounds x="152" y="80" width="838" height="510" />\n </bpmndi:BPMNShape>\n <bpmndi:BPMNShape id="Lane_103btcx_di" bpmnElement="Lane_103btcx" isHorizontal="true">\n <dc:Bounds x="182" y="370" width="808" height="220" />\n </bpmndi:BPMNShape>\n <bpmndi:BPMNShape id="Lane_06s1mba_di" bpmnElement="Lane_06s1mba" isHorizontal="true">\n <dc:Bounds x="182" y="80" width="808" height="290" />\n </bpmndi:BPMNShape>\n <bpmndi:BPMNEdge id="Flow_1gvp9xx_di" bpmnElement="Flow_1gvp9xx">\n <di:waypoint x="640" y="500" />\n <di:waypoint x="732" y="500" />\n </bpmndi:BPMNEdge>\n <bpmndi:BPMNEdge id="Flow_1ayl0cy_di" bpmnElement="Flow_1ayl0cy">\n <di:waypoint x="590" y="277" />\n <di:waypoint x="590" y="460" />\n </bpmndi:BPMNEdge>\n <bpmndi:BPMNEdge id="Flow_0gr7pas_di" bpmnElement="Flow_0gr7pas" bioc:stroke="rgb(142, 36, 170)" bioc:fill="rgb(225, 190, 231)">\n <di:waypoint x="308" y="237" />\n <di:waypoint x="540" y="237" />\n </bpmndi:BPMNEdge>\n <bpmndi:BPMNShape id="Activity_04admi2_di" bpmnElement="Activity_1d2rrr0" bioc:stroke="rgb(30, 136, 229)" bioc:fill="rgb(187, 222, 251)">\n <dc:Bounds x="540" y="197" width="100" height="80" />\n </bpmndi:BPMNShape>\n <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1" bioc:stroke="rgb(67, 160, 71)" bioc:fill="rgb(200, 230, 201)">\n <dc:Bounds x="272" y="219" width="36" height="36" />\n </bpmndi:BPMNShape>\n <bpmndi:BPMNShape id="Activity_0gs7hci_di" bpmnElement="Activity_1d2wp4b" bioc:stroke="rgb(0, 0, 0)" bioc:fill="rgb(255, 205, 210)">\n <dc:Bounds x="540" y="460" width="100" height="80" />\n </bpmndi:BPMNShape>\n <bpmndi:BPMNShape id="Event_0a8jrau_di" bpmnElement="Event_0a8jrau">\n <dc:Bounds x="732" y="482" width="36" height="36" />\n </bpmndi:BPMNShape>\n </bpmndi:BPMNPlane>\n </bpmndi:BPMNDiagram>\n</bpmn:definitions>\n', // 从接口获取的xml文件
};
},
watch: {},
created() {
this.getImg();
},
methods: {
getImg() {
// 初始时清除图层
this.bpmnViewer && this.bpmnViewer.destroy();
this.$refs.canvas.innerHTML = "";
this.scale = 1; // 放大缩小比例
// 初始化canvas
this.bpmnViewer = new BpmnViewer({
container: this.$refs.canvas,
height: 540, // 根据实际情况设置高度,宽度的话设置父元素的宽度就可以,会自适应的
});
const self = this;
const bpmnXmlStr = this.xmlUrl; // 从接口获取的xml文件
this.bpmnViewer.importXML(bpmnXmlStr, function (err) {
if (err) {
console.error(err);
} else {
let canvas = self.bpmnViewer.get("canvas");
canvas.zoom("fit-viewport", "auto");
// nodeCodes为需要设置高亮颜色的部分的id的集合(xml文件中<flowNodeRef>****</flowNodeRef>标签里的部分),这个数据也是从接口获取,这里从xml中随便取出几个测试用
let nodeCodes = [
"Activity_1d2rrr0",
"StartEvent_1",
"Activity_1d2wp4b",
];
// 调用设置高亮颜色class方法,这里可以根据接口获取的id集合情况,对不同的部分设置不同的class名,然后在css中设置样式
self.setNodeColor(nodeCodes, "nodeSuccess", canvas);
}
});
},
// 设置高亮颜色的class
setNodeColor(nodeCodes, colorClass, canvas) {
for (let i = 0; i < nodeCodes.length; i++) {
canvas.addMarker(nodeCodes[i], colorClass);
}
},
// 放大缩小,这里尽量设置flag的值小一点,这样每次放大缩小不会很多,避免放大超出父元素
handleZoom(flag) {
// 放大缩小倍数flag可以自行设置
if (flag < 0 && this.scale <= 1) {
return;
}
this.scale += flag;
this.$nextTick(() => {
this.bpmnViewer.get("canvas").zoom(this.scale);
});
},
},
};
</script>
<style scoped lang="scss">
.canvas {
margin: 10px;
}
>>> .nodeSuccess:not(.djs-connection) {
.djs-visual {
> :nth-child(1) {
stroke: #f70e0e !important;
stroke-width: 3px !important;
}
}
}
</style>