前言
Q: bpmn.js是什麼? ?️
”
bpmn.js是一個BPMN2.0渲染工具包和web建模器, 使得畫流程圖的功能在前端來完成.
Q: 我為什麼要寫該系列的教材? ?️
”
因為公司業務的需要因而要在專案中使用到bpmn.js
,但是由於bpmn.js
的開發者是國外友人, 因此國內對這方面的教材很少, 也沒有詳細的文件. 所以很多使用方式很多坑都得自己去找.在將其琢磨完之後, 決定寫一系列關於它的教材來幫助更多bpmn.js
的使用者或者是期於找到一種好的繪製流程圖的開發者. 同時也是自己對其的一種鞏固.
由於是系列的文章, 所以更新的可能會比較頻繁, 您要是無意間刷到了且不是您所需要的還請諒解?.
不求贊?不求心❤️. 只希望能對你有一點小小的幫助.
自定義ContextPad篇
經過前面幾章的學習, 相信大家都已經掌握了自定義palette
和renderer
, 這一章節主要講解的是自定義contextPad
.
先讓我們來回顧一下, contextPad
是什麼?
如圖, 可以看到除了在左側的工具欄處能新增節點之外, 點選節點的時候也會出現一個小彈窗, 這裡面也可以新增節點. 這個小彈窗就是 contextPad
.
那麼, 通過閱讀你可以學習到:
在預設的ContextPad
基礎上修改
前期準備
讓我們接著在LinDaiDai/bpmn-vue-custom案例專案上進行開發.
在components
資料夾下新建一個custom-context-pad.vue
檔案, 同時配置路由“自定義contextPad”.
在components/custom
資料夾下新建一個CustomContextPad.vue
檔案, 用來自定義contextPad
.
編寫CustomContextPad.vue
程式碼
其實自定義contextPad
和palette
很像, 只不過是使用contextPad.registerProvider(this)
來指定它是一個contextPad
, 而自定義palette
是用platette.registerProvider(this)
.
程式碼如下:
// CustomContextPad.js
export default class CustomContextPad {
constructor(config, contextPad, create, elementFactory, injector, translate) {
this.create = create;
this.elementFactory = elementFactory;
this.translate = translate;
if (config.autoPlace !== false) {
this.autoPlace = injector.get('autoPlace', false);
}
contextPad.registerProvider(this); // 定義這是一個contextPad
}
getContextPadEntries(element) {}
}
CustomContextPad.$inject = [
'config',
'contextPad',
'create',
'elementFactory',
'injector',
'translate'
];
複製程式碼
相信大家都已經看出來了, 重點還是在於getContextPadEntries
這個方法, 接下來讓我們來構建這個方法.
編寫getContextPadEntries
程式碼
其實這個方法, 需要返回的也是一個物件, 也就是你要在contextPad
這個容器裡顯示哪些自定義的元素, 比如我這裡需要給容器裡新增一個lindaidai-task
的元素, 那麼我們可以在返回的物件中新增上append.lindaidai-task
這個屬性.
而屬性值就是這個元素的一系列配置, 和palette
中一樣, 包括:
group: 屬於哪個分組, 比如 tools、event、gateway、activity
等等,用於分類className: 樣式類名, 我們可以通過它給元素修改樣式 title: 滑鼠移動到元素上面給出的提示資訊 action: 使用者操作時會觸發的事件
大概是這樣:
// CustomContextPad.js
getContextPadEntries(element) {
return {
'append.lindaidai-task': {
group: 'model',
className: 'icon-custom lindaidai-task',
title: translate('建立一個型別為lindaidai-task的任務節點'),
action: {
click: appendTask,
dragstart: appendTaskStart
}
}
};
}
複製程式碼
接下來就是構建appendTask
和appendTaskStart
// CustomContextPad.js
getContextPadEntries(element) {
const {
autoPlace,
create,
elementFactory,
translate
} = this;
function appendTask(event, element) {
if (autoPlace) {
const shape = elementFactory.createShape({ type: 'bpmn:Task' });
autoPlace.append(element, shape);
} else {
appendTaskStart(event, element);
}
}
function appendTaskStart(event) {
const shape = elementFactory.createShape({ type: 'bpmn:Task' });
create.start(event, shape, element);
}
return {
'append.lindaidai-task': {
group: 'model',
className: 'icon-custom lindaidai-task',
title: translate('建立一個型別為lindaidai-task的任務節點'),
action: {
click: appendTask,
dragstart: appendTaskStart
}
}
};
}
}
複製程式碼
這裡和palette
中有一點不同, 就是多了一層autoPlace
的判斷, 其實我也沒太搞明白這個autoPlace
的作用是什麼, 自動放置? 而且官方給的例子?就是這麼寫的, 有知道的小夥伴還請評論區留言哦, 謝謝~
修改contextPad
的相關樣式
此時我們看看效果吧?...
咿~ 好像可以耶, 但是, 這個小積木也太小了一點吧?, 而且滑鼠移上去之後, 黃色的背景色直接就覆蓋它了...
哇, 這不能忍啊...
得想法子解決它, 還我漂亮的小積木❤️...
接著讓我們開啟控制檯審查元素, 可以發現這個背景色是一個叫.djs-context-pad .entry
的類提供的樣式, 也許, 我們可以全域性修改這個樣式, 讓我們試試看:
/* app.css */
/* 自定義 contextPad 的樣式 */
.djs-context-pad .lindaidai-task.entry:hover {
background: url('hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/rules.png') center no-repeat!important;
background-size: cover!important;
}
.djs-context-pad .entry:hover { /* 重新修改了 hover 之後的樣式 */
border: 1px solid #1890ff;
}
複製程式碼
.djs-context-pad .entry {
box-sizing: border-box;
background-size: 94%;
transition: all 0.3s;
}
複製程式碼
開啟頁面看看效果哈.
不錯, 解決了, 哈哈?.
(直接修改樣式雖然不是最好的解決辦法, 但這是目前我能想到的辦法, 而且它確實也能夠解決問題)
完全自定義ContextPad
前期準備
同樣的, 如果你已經學會了在預設的ContextPad
基礎上修改, 那麼完全自定義ContextPad
也就差不多了?.
不過完全自定義ContextPad
不是叫contextPad
, 而是contextPadProvider
, 好像要更厲害一點?...
OK?, 讓我們在customModeler/custom
資料夾下新建一個CustomContextPadProvider.js
檔案.
編寫CustomContextPadProvider.js
程式碼
先讓我們來看下主要的結構:
// CustomContextPadProvider.js
export default function ContextPadProvider(contextPad, config, injector, translate, bpmnFactory, elementFactory, create, modeling, connect) {
this.create = create
this.elementFactory = elementFactory
this.translate = translate
this.bpmnFactory = bpmnFactory
this.modeling = modeling
this.connect = connect
config = config || {}
if (config.autoPlace !== false) {
this._autoPlace = injector.get('autoPlace', false)
}
contextPad.registerProvider(this)
}
ContextPadProvider.$inject = [
'contextPad',
'config',
'injector',
'translate',
'bpmnFactory',
'elementFactory',
'create',
'modeling',
'connect'
]
ContextPadProvider.prototype.getContextPadEntries = function(element) {}
複製程式碼
別看上面程式碼很長的樣子, 其實沒啥東西:
定義一個 ContextPadProvider
類, 然後引入一些我們後面要用到的方法或者屬性通過 $inject
注入進來重寫原型鏈上的 getContextPadEntries
方法
編寫getContextPadEntries
程式碼
你應該也發現了, 重點還是重寫getContextPadEntries
這個方法.
額, 這裡我先以一個簡單的為例, 先只是建立一個lindaidai-task
. 因此可以直接把在預設的ContextPad基礎上修改案例中的getContextPadEntries
中的程式碼複製過來:
// CustomContextPad.js
getContextPadEntries(element) {
const {
autoPlace,
create,
elementFactory,
translate
} = this;
function appendTask(event, element) {
if (autoPlace) {
const shape = elementFactory.createShape({ type: 'bpmn:Task' });
autoPlace.append(element, shape);
} else {
appendTaskStart(event, element);
}
}
function appendTaskStart(event) {
const shape = elementFactory.createShape({ type: 'bpmn:Task' });
create.start(event, shape, element);
}
return {
'append.lindaidai-task': {
group: 'model',
className: 'icon-custom lindaidai-task',
title: translate('建立一個型別為lindaidai-task的任務節點'),
action: {
click: appendTask,
dragstart: appendTaskStart
}
}
};
}
}
複製程式碼
此時讓我們先看看效果哈:
效果好像是實現了, 而且點選和拖拽它也能實現建立lindaidai-task
的效果...
但總感覺好像少了什麼, 因為光建立task
型別但元素是不夠的呀, 可不可以建立線或者實現編輯, 刪除元素的功能呢? 當然可以啦, 哈哈?.
不過這一章節先說這麼多, 如何建立線和實現編輯, 刪除我會把它放到一下章來細講哈?, 不用著急.
後語
上面?案例用的都是同一個專案?
專案案例Git地址: LinDaiDai/bpmn-vue-custom 喜歡的小夥伴請給個Star
?呀, 謝謝?
系列相關推薦: