bpmn是比较方便的绘制流程图的插件,官方demo https://github.com/bpmn-io/bpmn-js-examples
安装
1.HTML中使用,通过script标签引入
<script src="https://unpkg.com/[email protected]/dist/bpmn-modeler.development.js"></script>
2.npm安装bpmn-js
npm install bpmn-js
npm install bpmn-js-properties-panel
//节点信息编辑面板
使用
1.HTML中使用
var bpmnModeler = new BpmnJS({
container: '#canvas',
keyboard: {
bindTo: window
}
});
2.vue页面引入并使用bpmn
import BpmnModdle from 'bpmn-js'; //默认入口是Viewer.js文件,只有预览流程图的功能;
import BpmnModdle from 'bpmn-js/lib/Modeler'; //如果手动引入bpmn-js/lib/Modeler,则具备左侧工具栏,可以编辑流程图
<template>
<div style="">
<div id="js-canvas"></div>
<div id="js-properties-panel"></div>
<div>
<a-button @click="download">保存到本地</a-button>
<button @click="createNew">新建</button>
</div>
<!-- <a-modal></a-modal> -->
</div>
</template>
<script>
import BpmnModdle from 'bpmn-js/lib/Modeler';
import diagramXml from '../../../assets/diagram.bpmn'; //xml文件
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda';
export default {
name: 'bpmn',
data() {
return {
viewer: null,
canvas: null,
bpmnText: '',
}
},
mounted() {
this.$nextTick().then(() => {
this.canvas = document.getElementById('js-canvas')
this.viewer = new BpmnModdle({
container: this.canvas,
keyboard: {
bindTo: window
},
propertiesPanel: {
parent: '#js-properties-panel'
},
additionalModules: [
propertiesProviderModule
]
})
this.create()
})
},
methods: {
download() {
this.viewer.saveXML({ format: true }, (err, xml) => {
if (xml) {
this.bpmnText = xml
var a = document.createElement('a');
a.href = 'data:application/bpmn20-xml;charset=UTF-8,' + encodeURIComponent(xml)
a.download = 'diagram.bpmn';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
a = null;
}
})
},
create() {
this.bpmnText = diagramXml
this.viewer.importXML(diagramXml, err => {
if (err) {
throw (err)
}
this.viewer.get('canvas').zoom('fit-viewport')
var eventBus = this.viewer.get('eventBus');
var events = [
'element.click',
'element.dblclick'
]
events.forEach(event => {
eventBus.on(event, (e) => {
})
})
})
},
createNew() {
this.viewer.createDiagram(err => {
if (err) {
throw (err)
}
this.viewer.get('canvas').zoom('fit-viewport')
var eventBus = this.viewer.get('eventBus');
var events = [
'element.click',
'element.dblclick'
]
events.forEach(event => {
eventBus.on(event, (e) => {
// console.log(event, 'on', e.element.id)
})
})
})
}
}
}
</script>
<style>
//引入样式,否则显示不出内容
@import 'bpmn-js/dist/assets/diagram-js.css';
@import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
@import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
@import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
@import 'bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css';
</style>
左侧是节点选择区域,点击图标后,鼠标移动到右侧画布区域,点击后绘制图形;
点击图形节点,右侧弹出节点详细信息,可以对节点信息进行编辑, 如下图:
源码分析
以上功能主要通过Modeler来实现
1.新建Modeler实例
import BpmnModdle from 'bpmn-js/lib/Modeler';
var viewer = new
2.创建空白新流程图
//Modeler继承自Viewer
//importXML定义在Viewer中
var initialDiagram =
'<?xml version="1.0" encoding="UTF-8"?>' +
'<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
'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" ' +
'targetNamespace="http://bpmn.io/schema/bpmn" ' +
'id="Definitions_1">' +
'<bpmn:process id="Process_1" isExecutable="false">' +
'<bpmn:startEvent id="StartEvent_1"/>' +
'</bpmn:process>' +
'<bpmndi:BPMNDiagram id="BPMNDiagram_1">' +
'<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">' +
'<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">' +
'<dc:Bounds height="36.0" width="36.0" x="173.0" y="102.0"/>' +
'</bpmndi:BPMNShape>' +
'</bpmndi:BPMNPlane>' +
'</bpmndi:BPMNDiagram>' +
'</bpmn:definitions>';
Modeler.prototype.createDiagram = function(done) {
return this.importXML(initialDiagram, done);
};
3.创建指定流程图
//需要传入项xml: 流程图xml字符串 回调方法,创建完成后调用
Viewer.prototype.importXML = function(xml, bpmnDiagram, done) {
if (isFunction(bpmnDiagram)) {
done = bpmnDiagram;
bpmnDiagram = null;
}
// done is optional
done = done || function() {};
...//新建流程图操作
};
4.保存xml
//由源码可知,调用saveXML即可保存, 需要传入回调done,done里会传入参数保存后的xml内容。根据实际需要对xml进行处理
Viewer.prototype.saveXML = function(options, done) {
if (!done) {
done = options;
options = {};
}
var self = this;
...
this._moddle.toXML(definitions, options, function(err, xml) {
try {
xml = self._emit('saveXML.serialized', {
error: err,
xml: xml
}) || xml;
self._emit('saveXML.done', {
error: err,
xml: xml
});
} catch (e) {
console.error('error in saveXML life-cycle listener', e);
}
done(err, xml); //生成的xml会传入回调方法
});
};
5.保存为svg
//跟保存为xml操作一样,生成的svg信息会返回给回调,在回调里进行处理即可
Viewer.prototype.saveSVG = function(options, done) {
if (!done) {
done = options;
options = {};
}
this._emit('saveSVG.start');
var svg, err;
try {
var canvas = this.get('canvas');
var contentNode = canvas.getDefaultLayer(),
defsNode = domQuery('defs', canvas._svg);
var contents = innerSVG(contentNode),
defs = defsNode ? '<defs>' + innerSVG(defsNode) + '</defs>' : '';
var bbox = contentNode.getBBox();
svg =
'<?xml version="1.0" encoding="utf-8"?>\n' +
'<!-- created with bpmn-js / http://bpmn.io -->\n' +
'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' +
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ' +
'width="' + bbox.width + '" height="' + bbox.height + '" ' +
'viewBox="' + bbox.x + ' ' + bbox.y + ' ' + bbox.width + ' ' + bbox.height + '" version="1.1">' +
defs + contents +
'</svg>';
} catch (e) {
err = e;
}
this._emit('saveSVG.done', {
error: err,
svg: svg
});
done(err, svg);
};