跳到主要内容

自定义渲染器 CustomRenderer

· 阅读需 2 分钟
Yu Jianghao

如何自定义一个 bpmn-js 自定义渲染器(custom-renderer),将 bpmn:ServiceTask 渲染成一个(不怎么)漂亮的方块?

原理

首先要明白,bpmn-js 的渲染逻辑是通过 diagram-js 实现的,具体的是通过向 BaseRenderer 注册 Renderer 实现:

一个 Renderer 需要实现 IRenderer 接口,参见过去的文章

Renderer 需要在初始化时向 BaseRenderer 注册自己:

BaseRenderer.call(renderer, eventBus, renderPriority)

最后暴露为一个 Module 并且启用

实现

首先定义一个 Renderer,确定我们只能渲染 bpmn:ServiceTask

import {is} from 'bpmn-js/lib/util/ModelUtil'

class CustomRenderer {
canRender(element) {
return is(element, 'bpmn:ServiceTask');
}
}

然后实现 drawShape 画出想要的样子

import { is } from "bpmn-js/lib/util/ModelUtil";
import {
append as svgAppend,
attr as svgAttr,
create as svgCreate,
transform as svgTransform,
createTransform
} from "tiny-svg";
import BaseRenderer from "diagram-js/lib/draw/BaseRenderer";

class CustomRenderer {
drawShape(visuals, element) {
const container = svgCreate("g");
const rect = svgCreate("rect");
svgAttr(rect, {
fill: "#6647d2",
stroke: "#777",
strokeWidth: 1,
width: element.width,
height: element.height,
borderRadius: 10
});
svgAppend(container, rect);
const circle = svgCreate("circle");
svgAttr(circle, {
cx: 0,
cy: 0,
r: 25,
fill: "#f8cf45"
});
const translate = createTransform();
translate.setTranslate(element.width / 2, element.height / 2);
svgTransform(circle, translate);
svgAppend(container, circle);
svgAppend(visuals, container);
return container;
}
}

如果有需要,还可以通过 drawShapePath 画一下元素可视范围的路径,不过一般不需要。

然后将 CustomRenderer 注册到 BaseRenderer

class CustomRenderer {
constructor(eventBus) {
BaseRenderer.call(this, eventBus, 2000);
}
}
CustomRenderer.$inject = ['eventBus'];

导出一个 Module,并载入

export default {
__init__: ["customRenderer"],
customRenderer: ["type", CustomRenderer]
};

结果