• vue项目中使用bpmn-自定义platter


    内容概述

    本系列“vue项目中使用bpmn-xxxx”分为七篇,均为自己使用过程中用到的实例,手工原创,目前陆续更新中。主要包括vue项目中bpmn使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。如果转载或通过爬虫直接爬的,格式特别丑,请来原创看:我是作者原文

    前情提要

    经过前四篇的学习,我们能够实现bpmn基本绘图、预览、为节点加事件加颜色等效果,这一篇我们来说,如何自定义左侧工具栏(platter),首先看一下自定义前后效果图对比:

    我们本次要实现的目标:基于左侧platter原有元素类型,创建出一个新的自定义节点。暂且叫它“草莓蛋糕”节点,类型是 bpmn:Task, 样式我们自己找一个好看的小草莓蛋糕图案。所以,开动吧~首先新建一个“customPalette”文件夹,里面放我们今天所有自定义的文件。

    步骤1:建立platter类函数,命名为CustomPalette.js

    export default class CustomPalette {
      constructor(create, elementFactory, palette) {
        this.create = create;
        this.elementFactory = elementFactory;
        palette.registerProvider(this);
      }
     
     
      // 这个是绘制palette的核心,函数名不要变
      getPaletteEntries() {
        const elementFactory = this.elementFactory;
        const create = this.create;
     
        function dragEventFactory(type) {
          return function (event) {
            const taskShape = elementFactory.create('shape', {
              type: type
            });
            create.start(event, taskShape);
          };
        }
     
        return {
          'create.cake': {
            title: '我是自定义节点-草莓蛋糕',    // 鼠标悬浮到节点上显示的文字
            className: 'icon-custom bpmn-icon-cake',   // 样式名
            action: {      // 操作该节点时会触发的事件,此时只注册一个拖动事件即可,否则拖动时没有效果
              dragstart: dragEventFactory('bpmn:Task')
            }
          }
        };
      }
    }
    CustomPalette.$inject = [
      'create',
      'elementFactory',
      'palette'
    ];
    View Code

    此时,我们已经注册好了一个名称为“create.cake”的节点,拖动它时,画布中会出现一个"bpmn:Task"类型的节点,此时需要将该文件导出并在页面中引入,否则没有效果。

    步骤2:在CustomPalette.js同级,建立一个index.js文件将其导出

    import CustomPalette from './CustomPalette';
    export default {
      __init__: ['customPalette']
      customPalette: ['type', CustomPalette],
    };

    步骤3:页面中(index.vue)引入index.js

    import customModule from './customPalette';
    export default {
      mounted() {
        this.containerEl = document.getElementById('container');
        this.bpmnModeler = new BpmnModeler({
           additionalModules: [ customModule ]
        });
    }

    步骤4:为节点定义样式

    新建一个customPalette.scss文件,在该文件同级放一张“cake.png”的图片,作为节点的背景图写入。背景图引入的话,貌似只支持.png格式,亲测:jpg报错

    .bpmn-icon-cake {
      background-image: url('./cake.png');
    }
     
    .icon-custom {
      background-size: 65%;
      background-repeat: no-repeat;
      background-position: center center;
    }

    并且在main.js中引入,注意,一定要在main.js中全局引入,否则不生效。

    import 'customPalette/customPalette.scss';

    此时,我们便可以在左侧工具栏中看到自定义的“草莓蛋糕”节点了,但是此时拖动该节点,右侧只会产生一个“bpmn:Task”的节点,只有一个框框。

    我们希望的是,拖动后画布中也显示自定义图标,所以我们进行下一步:自定义渲染

    步骤5:画布渲染自定义节点

    此时需要我们新建一个 CustomRenderer.js文件,作用:自定义 renderer。因为我们是在bpmn原有的元素“bpmn:Task”基础上进行修改,所以我们需要对将BaseRenderer进行继承。

    import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer'; // 引入默认的renderer
     
    const HIGH_PRIORITY = 1500; // 最高优先级
     
    export default class CustomRenderer extends BaseRenderer {
      // 继承BaseRenderer
      constructor(eventBus, bpmnRenderer) {
        super(eventBus, HIGH_PRIORITY);
        this.bpmnRenderer = bpmnRenderer;
      }
     
      canRender(element) {
        return !element.labelTarget;
      }
     
      drawShape(parentNode, element) {
        const shape = this.bpmnRenderer.drawShape(parentNode, element);
        return shape;
      }
     
      getShapePath(shape) {
        return this.bpmnRenderer.getShapePath(shape);
      }
    }
     
    CustomRenderer.$inject = ['eventBus', 'bpmnRenderer'];
    View Code

    此时, CustomRenderer.js文件大概结构完成了,注意:HIGH_PRIORITY变量和canRender不可以删掉,否则会有问题。重头戏是里面的drawShape函数。

    步骤6:书写drawShape函数

    我们在CustomRenderer.js同级建立一个util文件,记录自定义类型节点的一些属性。

    import cake from './cake.png';
    
    // 自定义元素的类型,此时我们只需要自定义一种节点,所以数组只有一个元素
    const customElements = ['bpmn:Task']; 
    const customConfig = {
      // 自定义元素的配置
      cake: {
        url: cake,
        attr: {x: 0, y: 0,  50, height: 50}
      }
    };
     
    export {customElements, customConfig};

    现在我们来书写drawShape函数

    import { customElements, customConfig } from './util';
    import { append as svgAppend, create as svgCreate } from 'tiny-svg';
    ...
    drawShape(parentNode, element) {
      const type = element.type; // 获取到类型
      // 所有节点都会走这个函数,所以此时只限制,需要自定义的才去自定义,否则仍显示bpmn默认图标
      if (customElements.includes(type)) {  
        const {url, attr} = customConfig['cake'];
        const customIcon = svgCreate('image', {...attr, href: url});
        element['width'] = attr.width;
        element['height'] = attr.height;
        svgAppend(parentNode, customIcon);
        return customIcon;
      }
      const shape = this.bpmnRenderer.drawShape(parentNode, element);
      return shape;
    }

    步骤7: 导出并使用CustomRenderer

    修改之前导出CustomPalette的 index.js文件

    import CustomPalette from './CustomPalette';
    import CustomRenderer from './CustomRenderer';
     
    export default {
      __init__: ['customPalette', 'customRenderer'],
      customPalette: ['type', CustomPalette],
      customRenderer: ['type', CustomRenderer]
    };

    注意:此时__init__内的属性名都不可以改,不要问为什么,因为改了报错。

    步骤3中已经将该index.js引入到了页面中,此时无需再次引入,此时我们来看看效果。

     后续

    项目目录:index.vue是画布主页面,同级customPalette文件夹下共有6个文件,结构如下:

     

    各个文件的代码片段在文中已经展示过了,按照步骤写下来应该是没问题的。想传源码上来,但是文件夹不知道怎么上传到博客。如想获取完整源码或有问题,可以公众号联系我,扫下面二维码或公众号搜“前端便利贴”,即可获取~

     可爱的你可能还需要

  • 相关阅读:
    符号运算·
    笔记1
    Linux
    三数比较
    JavaScript变量,作用域和内存
    在HTML中使用JavaScript
    JavaScript基本概念
    JavaScript简介
    上机考试反思与总结
    计算机科学与技术学习方法
  • 原文地址:https://www.cnblogs.com/lemoncool/p/12870119.html
Copyright © 2020-2023  润新知