bpmn.js + vue + vuex的业务实现——节点增加图片和样式改变

1,284 阅读3分钟

自定义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', ''], //禁用单个图形拖动
          },
        ],
      });

完整文件目录展示

image.png

  • custom 文件用于编写自定义renderer
  • utils用于存储图片及文字数据
  • customRenderer.vue是用于渲染流程图

系列文章目录