Самый подробный обучающий материал по bpmn.js во всей сети - пользовательская палитра

внешний интерфейс
Самый подробный обучающий материал по bpmn.js во всей сети - пользовательская палитра

предисловие

В: Что такое bpmn.js?

"

bpmn.jsЭто набор инструментов рендеринга BPMN2.0 и средство веб-моделирования, которое позволяет выполнять функцию рисования блок-схем во внешнем интерфейсе.

В: Почему я пишу эту серию учебников? 🤔️

"

Из-за потребностей бизнеса компании его необходимо использовать в проектеbpmn.js, Однако из-заbpmn.jsРазработчики игры зарубежные друзья,поэтому отечественных методических материалов мало и нет подробных документов.Поэтому много способов использования и много ям приходится искать самому.Поразмыслив,решил написать серию учебные материалы об этом. чтобы помочь большеbpmn.jsПользователи или разработчики, которые ищут хороший способ рисовать блок-схемы, в то же время для них это еще и своего рода консолидация.

Поскольку это серия статей, она может часто обновляться.Пожалуйста, простите меня, если вы случайно смахнули его, и это не то, что вам нужно😊.

Не просите похвалы👍 не просите сердца❤️ Я просто надеюсь, что смогу вам немного помочь.

Статьи пользовательской палитры

После базовых туториалов в предыдущих главах я считаю, что все правыbpmn.jsОсновное использование .

Начиная с этой главы, я объясню некоторыеbpmn.jsНастраиваемые разделы в , включая настраиваемую левую панель инструментов, настраиваемую визуализацию, настраиваемуюcontextPadи т.п.

Давайте сначала посмотрим на картинку, чтобы увидеть, что есть на наших страницах рисования:

В этой главе я хочу рассказать, как настроить панель инструментов слева (Palette, также называемая палитрой), читая вы можете узнать:

Для каталога выше 👆 неявное значение заключается в настройкеPaletteЕсть два способа:

  • существуетbpmn.jsпредоставляется по умолчаниюPaletteИзмените его (или добавьте новый элемент)
  • полное покрытиеPaletteВсе предметы в, настроить новыйPalette

Изменить на основе палитры по умолчанию

Давайте рассмотрим первый и самый простой, мы добавляем пользовательский элемент в официальную палитру.

  • Тип элемента:bpmn:Task
  • Имя элемента:lindaidai-task
  • стиль: следоватьbpmn:TaskОригинальный стиль, просто поменяйте рамку на красную
  • Роль: создать типlindaidai-taskузел задачи

Эффект такой:

bpmnCustom1.png
bpmnCustom1.png

Как показано выше, только цвет окна задачи меняется на красный, поэтому эффект не очень очевиден, вы даже можете изменить его напрямую:

bpmnCustom2.png
bpmnCustom2.png

Давайте посмотрим, как это сделать! 🐶

Предварительная подготовка

Поскольку это новая глава, здесь я также создаю новый проект:

$ vue create bpmn-vue-custom
$ npm i vue-router axios bpmn-js-properties-panel bpmn-js --save-D

По предыдущему случаюLinDaiDai/bpmn-vue-basicНастройте соответствующую маршрутизацию и так далее.

существуетcomponentsСоздайте новую папку с именемcustom-palette.vueфайл, и будетprovider.vue(предыдущий базовый вариант) копируется.

продолжатьcomponentsСоздайте новую папку под папкойcustomИспользуется для хранения некоторых пользовательских вещей, которые мы напишем позже.

Давайте посмотрим на нашу текущую структуру проекта:

я уже вcustomСоздана новая папкаCustomPalette.js, следующим шагом будет запись в нем элементов, которые мы хотим настроить.

записыватьCustomPalette.jsкод

Сначала этоjsЯвляется экспортом класса (имя класса можно брать по желанию, но нельзя брать его по желанию при обращении к нему, о чем речь пойдет позже):

вот и я так понимаюCustomPalette:

// CustomPalette.js
export default class CustomPalette {
    constructor(bpmnFactory, create, elementFactory, palette, translate) {
        this.bpmnFactory = bpmnFactory;
        this.create = create;
        this.elementFactory = elementFactory;
        this.translate = translate;

        palette.registerProvider(this);
    }
    // 这个函数就是绘制palette的核心
    getPaletteEntries(element) {}
}

CustomPalette.$inject = [
    'bpmnFactory',
    'create',
    'elementFactory',
    'palette',
    'translate'
]

Код выше 👆 легко понять:

  • определить класс
  • использовать$injectВведите некоторые необходимые переменные
  • использовать в классеpalette.registerProvider(this)указать, что этоpalette

определенныйCustomPalette.jsПосле этого нам нужноindex.jsэкспортировать его в:

// custom/index.js
import CustomPalette from './CustomPalette'

export default {
    __init__: ['customPalette'],
    customPalette: ['type', CustomPalette]
}

Примечание: ️здесь__init__Имя должно бытьcustomPalette, и следующие имена атрибутов также должны бытьcustomPalette, иначе будет сообщено об ошибке.

Также использовать его на странице:

<!--custom-palette.vue-->
<script>
...
import customModule from './custom'
...
this.bpmnModeler = new BpmnModeler({
...
    additionalModules: [
        // 左边工具栏以及节点
        propertiesProviderModule,
        // 自定义的节点
        customModule
    ]
})

</script>

Напишите основные функцииgetPaletteEntriesкод

Отложив это в сторону, вопрос в том, как построить этоgetPaletteEntriesфункция

Нельзя менять имя функции, иначе будет сообщено об ошибке.Во-первых, она возвращает объект, а объект, указанный в объекте, и есть тот элемент, который вы хотите настроить.Наверное, это выглядит так:

// CustomPalette.js
getPaletteEntries(element) {
    return {
        'create.lindaidai-task': {
            group: 'model', // 分组名
            className: 'bpmn-icon-task red', // 样式类名
            title: translate('创建一个类型为lindaidai-task的任务节点'),
            action: { // 操作
                dragstart: createTask(), // 开始拖拽时调用的事件
                click: createTask() // 点击时调用的事件
            }
        }
    }
}

Вы можете видеть, что имя элемента, которое я определил:create.lindaidai-task, Он будет иметь несколько фиксированных свойств:

  • группа: к какой группе он принадлежит, напримерtools、event、gateway、activityд., для классификации
  • className: имя класса стиля, мы можем использовать его для изменения стиля элемента
  • title: Подсказка, отображаемая над элементом при перемещении мыши.
  • действие: событие, которое будет запущено, когда пользователь выполнит действие

Все, что нам нужно сделать дальше, это:

  1. пройти черезclassNameустановить стиль
  2. пройти черезactionчтобы определить, что запускать

записыватьclassNameкод

я здесьscrсоздал новый в каталогеcssфайл, который используется для хранения некоторых глобальных стилей, иmain.jsСсылка на этот глобальный стиль в:

// main.js
// 引入全局的css
import './css/app.css'

Затем добавьте к нему следующие стили:

/* app.css */
.bpmn-icon-task.red {
    color: #cc0000 !important;
}

выше 👆classNameпочему я используюbpmn-icon-task, потому что классbpmn.jsодин изiconfontкласс, который можно использовать для реализацииtaskЭффект значка:

из-заiconfontэто шрифт, поэтому здесь я используюcolorизменить его цвет.

Вы также можете использовать его, если хотите полностью заменить его картинкой.classNameреализовать:

/* app.css */
.icon-custom { /* 定义一个公共的类名 */
    border-radius: 50%;
    background-size: 65%;
    background-repeat: no-repeat;
    background-position: center;
}

.icon-custom.lindaidai-task { /* 加上背景图 */
    background-image: url('https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/rules.png');
}

затем изменитьcreate.lindaidai-taskсерединаclassName:

// CustomPalette.js
 'create.lindaidai-task': {
    className: 'icon-custom lindaidai-task' 
 }

Эта страница - это фоном идет в вашем определении отображаемого:

bpmnCustom4.png
bpmnCustom4.png

записыватьactionкод

Фактически, после выполнения вышеуказанной операции страница может нормально отображать пользовательский элемент, но при нажатии или перетаскивании он не будет иметь никакого эффекта💦.

Что мы ожидаем в этот момент, так это щелкнуть или перетащить его, чтобы нарисоватьlindaidai-task, поэтому вам нужно добавить к нему события, То есть написать функцию для созданияbpmn:TaskЭтот элемент:

// CustomPalette.js
function createTask() {
    return function(event) {
        const businessObject = bpmnFactory.create('bpmn:Task');
        const shape = elementFactory.createShape({
            type: 'bpmn:Task',
            businessObject
        });
        console.log(shape) // 只在拖动或者点击时触发
        create.start(event, shape);
    }
}

Ядро здесь на самом деле использоватьbpmn.jsПредусмотрены некоторые способы созданияshapeЗатем добавьте его на холст.

(Я демонстрирую здесь созданиеbpmn:Taskэлемент, вы также можете использовать для созданияbpmn:StartEvent、bpmn:ServiceTask、bpmn:ExclusiveGatewayтак далее...)

В этот момент вы перетаскиваете или нажимаетеlindaidai-taskвы можете создать страницуTaskэлемент.

мы видим, хотяlindaidai-taskПанель инструментов слева золотая, но фактическая страница все еще отображается в «голом» состоянии😅, что как-то связано с пользовательским рендерингом, не волнуйтесь, это будет рассмотрено в следующих главах.

полныйCustomPalette.jsкод

Давайте соберем весь приведенный выше код вместе:

// CustomPalette.js
export default class CustomPalette {
    constructor(bpmnFactory, create, elementFactory, palette, translate) {
        this.bpmnFactory = bpmnFactory;
        this.create = create;
        this.elementFactory = elementFactory;
        this.translate = translate;

        palette.registerProvider(this);
    }

    getPaletteEntries(element) {
        const {
            bpmnFactory,
            create,
            elementFactory,
            translate
        } = this;

        function createTask() {
            return function(event) {
                const businessObject = bpmnFactory.create('bpmn:Task'); // 其实这个也可以不要
                const shape = elementFactory.createShape({
                    type: 'bpmn:Task',
                    businessObject
                });
                console.log(shape) // 只在拖动或者点击时触发
                create.start(event, shape);
            }
        }

        return {
            'create.lindaidai-task': {
                group: 'model',
                className: 'icon-custom lindaidai-task',
                title: translate('创建一个类型为lindaidai-task的任务节点'),
                action: {
                    dragstart: createTask(),
                    click: createTask()
                }
            }
        }
    }
}

CustomPalette.$inject = [
    'bpmnFactory',
    'create',
    'elementFactory',
    'palette',
    'translate'
]

Git-адрес кейса проекта:LinDaiDai/bpmn-vue-custom

Примечание: В случае с проектом для удобства демонстрации вcustom-paletteПредставлен вImportJS/onlyPalette.js, а рассмотренный выше случай основан на введенииcustom/index.jsДля того, чтобы объяснить, это надо самому понять, как различать.

Полностью настраиваемая палитра

Можно видеть, что описанный выше метод реализации 👆 фактически определяетCustomPaletteзатем вnew BpmnModelerссылка в сгенерированном объекте.

Но это немного плохо👎, то есть, если вы не хотите, чтобы элементы по умолчанию, которые он предоставляет, такие как начальные узлы, конечные узлы и узлы задач, но все они настраиваются под вас, вы не можете быть удовлетворены . Например:

bpmnCustom6.png
bpmnCustom6.png

В этот момент вам нужно переписатьBpmnModelerВ этом классе реализован собственный уникальный наборmodeler.

Предварительная подготовка

Продолжайте создавать его на основе проекта выше 👆customModelerИ папкаcustom-modeler.vueдокумент. затем вcustomModelerсоздатьindex.jsс однимcustomпапка.

  • customModelerФайлы в папке используются для установки пользовательскихmodeler
  • custom-modeler.vueОтображать как страницу (не забудьте настроить маршрутизацию страницы)

На данный момент структура проекта становится:

bpmnCustom7.png
bpmnCustom7.png

записыватьCustomPalette.jsкод

здесьCustomPalette.jsСпособ написания отличается от первого:

/**
 * A palette that allows you to create BPMN _and_ custom elements.
 */
export default function PaletteProvider(palette, create, elementFactory, globalConnect) {
    this.create = create
    this.elementFactory = elementFactory
    this.globalConnect = globalConnect

    palette.registerProvider(this)
}

PaletteProvider.$inject = [
    'palette',
    'create',
    'elementFactory',
    'globalConnect'
]

PaletteProvider.prototype.getPaletteEntries = function(element) { // 此方法和上面案例的一样
    const {
        create,
        elementFactory
    } = this;
    function createTask() {
        return function(event) {
            const shape = elementFactory.createShape({
                type: 'bpmn:Task'
            });
            console.log(shape) // 只在拖动或者点击时触发
            create.start(event, shape);
        }
    }
    return {
        'create.lindaidai-task': {
            group: 'model',
            className: 'icon-custom lindaidai-task',
            title: '创建一个类型为lindaidai-task的任务节点',
            action: {
                dragstart: createTask(),
                click: createTask()
            }
        }
    }
}

Вот прямая перепискаPaletteProviderЭтот класс также переопределяетgetPaletteEntriesметод, чтобы добиться эффекта закрытия исходной панели инструментов.

(Не смотрите на то, что написано выше 👆, кажется, много, но на самом деле успокоится и увидит, что это ничто 😊)

записыватьcustom/index.jsкод

Следующий шаг такой же, как и первый метод, нам нужно настроитьPaletteЭкспорт:

// custom/index.js
import CustomPalette from './CustomPalette'
export default {
    __init__: ['paletteProvider'],
    paletteProvider: ['type', CustomPalette]
}

Но здесь мы не используемcustomPalette, но напрямую использоватьpaletteProvider.

записыватьcustomModeler/index.jsкод

Самый важный шаг — написатьCustomModelerЭтот класс имеет:

import Modeler from 'bpmn-js/lib/Modeler'
import inherits from 'inherits'
import CustomModule from './custom'
export default function CustomModeler(options) {
    Modeler.call(this, options)
    this._customElements = []
}
inherits(CustomModeler, Modeler)
CustomModeler.prototype._modules = [].concat(
    CustomModeler.prototype._modules, [
        CustomModule
    ]
)

Экспортируемый класс наследуетModelerЭтот базовый класс обеспечивает реализацию других функций.

Цитата на странице

Последним шагом является преобразование нашего исходногоBpmnModelerСозданный объект изменяется нашим кастомнымCustomModelerсоздавать, писатьcustom-modeler.vue.

<!--custom-modeler.vue-->
<script>
...
import CustomModeler from './customModeler'
...
this.bpmnModeler = new CustomModeler({ // 原本是用BpmnModeler
    ...
    additionalModules: [] // 可以不用引用任何东西
})
</script>

Заходите и откройте страницу, чтобы увидеть эффект:

bpmnCustom8.png
bpmnCustom8.png

послесловие

В приведенном выше 👆 в обоих случаях используется один и тот же проект🦐

Git-адрес кейса проекта:LinDaiDai/bpmn-vue-customЕсли вам это нравится, пожалуйста, дайтеStar🌟 Да, спасибо😊

Полный каталог серии можно найти здесь:"Самый подробный учебник по bpmn.js во всей сети"

Рекомендации по сериалу:

"Самый подробный учебник по bpmn.js во всей сети - основы"

"Самый подробный учебный материал по bpmn.js во всей сети - http запрос"

"Самый подробный учебный материал по bpmn.js во всей сети - мероприятия"

"Самый подробный учебник по bpmn.js во всей сети - рендерер"

"Самый подробный учебник по bpmn.js во всей сети - contextPad"

"Самый подробный учебник по bpmn.js во всей сети - редактирование и удаление узлов"