自定义renderer
前言
上一章节我们介绍了关于bpmn.js如何与后台进行交互的问题以及如何渲染的问题, 要是不了解的小伙请移步
bpmn.js + vue + vuex的业务实现——http请求
这一章节主要讲解的是关于bpmn.js如何自定义renderer给节点增加图片和底色改变
开源链接
gitee:gitee.com/zh-howe/bpm…
节点增加图片
新建custom文件夹
新建一个custom文件夹用于存放自定义的文件,在其下新建CustomRenderer.js和index.js两个文件。bpmn.js除了能够自定义renderer,还可以自定义 Palette、自定义 contextPad
CustomRenderer.js
CustomRenderer.js是自定义renderer的核心代码,我们需要创建一个类CustomRenderer,用它继承bpmn.js的BaseRenderer类,我们就可以完美保留使用bpmn.js原来的renderer功能的同时,实现我们自己的功能和样式。
首先引入BaseRenderer类
import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
根据需要引入svg的操作方式
import {
append as svgAppend,
attr as svgAttr,
create as svgCreate,
select as svgSelect,
selectAll as svgSelectAll,
clone as svgClone,
clear as svgClear,
remove as svgRemove,
} from 'tiny-svg';
const HIGH_PRIORITY = 1500;
export default class CustomRenderer extends BaseRenderer {
constructor(eventBus, bpmnRenderer, modeling) {
super(eventBus, HIGH_PRIORITY);
this.bpmnRenderer = bpmnRenderer;
this.modeling = modeling;
}
canRender(element) {
// ignore labels
return !element.labelTarget;
}
/**
* 自定义节点图形
* @param {*} parentNode 当前元素的svgNode
* @param {*} element
* @returns
*/
drawShape(parentNode, element) {
const shape = this.bpmnRenderer.drawShape(parentNode, element);
const { type, width, height} = element;
//网关用图片替换
if (type === 'bpmn:ExclusiveGateway') {
svgAttr(parentNode, 'class', 'djs-visual gateway-grey');
const attr = { x: -7, y: 5, width: 65, height: 42 };
const customIcon = svgCreate('image', {
...attr,
href: require('@/images/workflow/gateway.png')
});
svgAppend(parentNode, customIcon);
return customIcon;
}
//把label文字换行
if (type == 'bpmn:UserTask' && !!element.businessObject.name) {
// 获取label
const text = svgSelect(parentNode, 'text');
const tspan = svgSelectAll(text, 'tspan');
// 偏移label
const tspanText = element.businessObject.name;
if (tspan?.length > 1) {
svgAttr(tspan[0], 'x', 40);
svgAttr(tspan[1], 'x', 25);
// 重写label,换行
if (tspanText.includes('(')) {
console.log(tspanText);
tspan[0].innerHTML = tspanText.split('(')[0];
tspan[1].innerHTML = '(' + tspanText.split('(')[1];
} else if (tspanText.includes('(')) {
console.log(tspanText);
tspan[0].innerHTML = tspanText.split('(')[0];
tspan[1].innerHTML = '(' + tspanText.split('(')[1];
}
if (tspanText.split('(')[1]?.length < 5 || tspanText.split('(')[1]?.length < 5) {
svgAttr(tspan[1], 'x', 35);
}
} else {
svgAttr(tspan[0], 'x', 35);
}
const attr = { x: width / 20, y: height / 3, width: 25, height: 25 };
// 给节点添加class以更改样式
svgAttr(parentNode, 'class', 'unActivities');
// 节点增加图片
const customIcon = svgCreate('image', {
...attr,
href: require('@/images/workflow/apply.png'),
});
svgAppend(parentNode, customIcon);
return customIcon;
}
return shape;
}
getShapePath(shape) {
return this.bpmnRenderer.getShapePath(shape);
}
}
drawShape的方法是bpmn.js绘制不同的节点所必须调用的方法,我们可以在这方法里做文章,自定义节点。
底色改变
svgAttr(parentNode, 'class', 'unActivities');给所在节点添加了class之后就可以配合css更改样式。
//customRenderer.less
.djs-visual.unActivities {
// 去除默认图标
path {
display: none !important;
}
// 底色改变
rect {
fill: #f7f8fb !important;
stroke: #f7f8fb !important;
}
// 文字样式改变
.djs-label {
font-weight: bold !important;
fill: #202020 !important;
font-size: 10px !important;
}
}
导出自定义的renderer
index.js用于导出自定义的renderer
//index.js
import CustomRenderer from './CustomRenderer';
export default {
__init__: ['customRenderer'],
customRenderer: ['type', CustomRenderer],
};
导入自定义的renderer
导入index.js文件,在建模时导入
//customRenderer.vue
import CustomModule from '@/components/bpmn-custom/custom/index';
// 建模
this.bpmnModeler = new BpmnModeler({
container: canvas,
additionalModules: [
CustomModule,
{
labelEditingProvider: ['value', ''], //禁用节点编辑
contextPadProvider: ['value', ''], //禁用图形菜单
bendpoints: ['value', {}], //禁用连线拖动
// zoomScroll: ["value", ""], //禁用滚动
// moveCanvas: ['value', ''], //禁用拖动整个流程图
move: ['value', ''], //禁用单个图形拖动
},
],
});
完整文件目录展示
- custom 文件用于编写自定义renderer
- utils用于存储图片及文字数据
- customRenderer.vue是用于渲染流程图