LogicFlow 脫胎於滴滴技術團隊在客服業務下的實踐,是由智能中臺—體驗平臺研發的一款流程可視化的前端框架,提供了一系列流程圖交互、編輯所必需的功能和靈活的節點自定義、插件等拓展能力,方便咱們快速在業務系統內知足類流程圖編輯器的需求。目前,LogicFlow 已經在公司內外不一樣用戶的流程配置需求中獲得了驗證。前端
首先,智能中臺—體驗平臺技術團隊幾乎支持了滴滴全部業務板塊客服系統的訴求,面對多樣性、邏輯變動快的業務場景,傳統的面向場景編程成本高且週期長。所以咱們建設了線上配置化的運營系統,讓運營、產品同窗可以經過畫流程圖的方式變動線上的業務邏輯,好比用戶電話進線時的互動式語音應答、人工客服在處理用戶進線時的標準做業流程、用戶自助解決問題的 H5 頁面配置系統等千人千面的應用場景。vue
其次,各業務系統雖然都須要應用流程可視化技術,但需求各不相同。有的對流程圖的要求比較簡單,圖的數據格式也簡單,而有的須要按照 BPMN 的規範來繪製流程圖,對於定製化的要求較高。咱們調研了市面上相關的框架 (BPMN.js、X六、Jsplumb、G6-editor),均存在不知足的場景,技術棧統一的成本很高。具體表如今:node
所以,咱們在 2020 上半年開啓了 LogicFlow 的項目,支持各系統的流程可視化需求。react
LogicFlow 當前已具有了哪些能力呢,我會分兩部分來介紹。git
提供了一個流程圖編輯所必需的各項能力,這也是 LogicFlow 的基礎能力:程序員
經過以上能力,前端研發能夠低成本、快速的搭建起流程可視化的應用,提供流暢的產品交互。下面是經過 LogicFlow 內置的節點和配套能力,作的流程圖示例:github
當基礎能力沒法知足業務需求的時候,便須要基於業務場景拓展。這也是 LogicFlow 能支持客服側多個系統的關鍵所在。算法
基於上述拓展的能力,前端研發可以根據實際業務場景的需求,靈活的開發出所需的節點、組件等。下面有兩個基於 LogicFlow 拓展能力作出的流程圖:編程
BPMN:小程序
審批流程:
上圖是經過橫縱兩個維度來對比目前你們耳熟能詳的幾個開源框架,以瞭解 LogicFlow 的定位。橫軸是該框架在圖可視化能力的豐富程度,縱軸越靠上則表明這個框架在業務流程應用上的成熟度越高,初次部署的開發成本越低。 讓咱們分別來介紹一下這幾個框架:
LogicFlow 的定位在上圖的 Bpmn.js 和 X6 之間,填補中間的空白。核心提供了流程圖的編輯器,而且經過拓展能力來支持 BPMN 等規範所需的流程節點和數據格式,以知足當前業務下的現狀。
核心包 @logicflow/core
提供了流程圖編輯器基礎的能力,右邊的 @logicflow/extension
是基於 @logicflow/core
的拓展性開發的插件。
主要介紹一下實現流程圖編輯器重要的選型和方案設計。
前端繪製圖形無非就是 HTML + CSS、Canvas、Svg 三種方式,咱們綜合作了一下對比,列出了相應的優劣勢:
在流程圖的場景下,不須要渲染大量的節點(最多幾千個元素),對於動畫的訴求也不高。Svg 基於 DOM 的特性會更適合咱們,一個是學習成本和開發成本更低,另外一個是基於 DOM 能夠作的拓展也更多。不過 Svg 標籤內部並不支持插入其餘好比 div 這種標籤,因此在實現某些功能的時候,都須要結合其餘 HTML 標籤。
因此最終咱們選擇使用 HTML + Svg 來完成圖的渲染,Svg 負責圖形、線的部分,HTML 來實現文本、菜單、背景等圖層。
基於上述方案,下一步咱們要作的是對實現一張流程圖作分類和抽象。
經過上圖:
由於流程圖是富交互或者說是重編輯的,有了這幾個基礎的模塊,接下來要作的就是富交互的方案設計,即用戶在圖上作的任何操做都要給出響應。好比我觸發一個節點的拖拽,那關聯的線可能須要跟着動,還能識別出在某個水平線上有沒有其餘節點(對齊線)。
首先咱們考慮到整個圖編輯器具有不少狀態存儲,而且要實現編輯圖上各模塊的響應就必需要有狀態的通訊能力。第二若是要實現相似 redo/undo 這類功能,那整個圖就必定須要根據數據得出渲染,即 fn(state) => View ,比較好的方式就是經過 Model 來驅動 View。
最終咱們選擇基於 MVVM,這個普遍被應用於當前前端工程中的設計模式來構建 LogicFlow 的圖編輯器,定義圖的 View 和 Model 層,使工程代碼具有必定的解耦。與此同時,引入 Mobx 來實現咱們的狀態管理、數據響應的能力,一張圖基於一份 Model 作狀態的通訊。此外,考慮 Mobx 的另外一個緣由是:只要我想,那就能夠作到最細顆粒度的數據綁定(觀測),能夠減小不必的渲染。
如下是 LogicFlow 圖編輯器的 MVVM 示意圖:
經過上圖能夠看到,View 層(圖、節點等)經過數據綁定,會在 Model 發生變化以後作出響應/更新。前面咱們提到了關於圖的渲染咱們是基於 Svg + HTML 實現的,那要作 View 層的更新無非就是命令式和聲明式兩個選擇:
$('.rectNode').attrs({x: 1, y: 2})
,像這種方式操做 DOM 代碼其實比較繁瑣,在重交互的場景下寫的代碼會比較冗餘。雖然咱們最終找到了有一個庫可以很方便的支持經過命令式的方式來繪圖 —— antv/g除了考慮到命令式在操做 DOM 的場景下寫代碼會比較繁瑣以外,還有一個緣由就是操做 DOM 的成本問題,在基於 State 更新 UI 的設計下,咱們天然而然想到了引入 Virtual DOM 來解決某些場景下的更新效率,這也能夠必定程度上彌補「基於 Svg 渲染圖形」可能形成的渲染性能問題。
總之,選擇 MVVM 的設計模式並引入 Virtual DOM,最根本的兩個緣由即是提高咱們圖編輯器場景下的開發效率,以及在 HTML + Svg 的圖渲染方案下,能夠追求更好的性能表現。
咱們與 X6 作了一次渲染時的性能比較,在相同的運行環境下,分別測出 LogicFlow 和 X6 在不一樣量級的節點/線下,渲染出流程圖的時間,理論上渲染時間越短,性能表現越好。
經過上述表格,咱們測算出 LogicFlow 在初始渲染速度上是優於 X6 的,而且這尚未開啓LogicFlow 的按需加載功能,也驗證了咱們的技術選型。你也能夠在示例頁進行測試: yhlchao.github.io/LF-VS-Other…
介紹了在 「狀態」 和 「響應」 咱們作的設計,那要收集到用戶的各種 「操做」 並及時上報和冒泡,就須要一套事件系統。最主要的就是複用和統一上報。
複用即怎麼保證全部節點和線都能具有默認的事件回調,以及針對復瑣事件(拖拽)的處理邏輯如何共用。
emit(ev, args)
都上報到 EventCenter,最終冒泡到 LogicFlow 類,由 LogicFlow 類統一跟宿主交互。此外,圖編輯器內任何地方也均可以經過 EventCenter 作事件的觸發和監聽工具中心的定位是解決某類特定問題的 utils,好比上面提到的 Behavior(復瑣事件的封裝) 和 EventCenter。此外,在圖編輯的過程當中,若是要實現比較好的交互效果,實際有不少複雜的計算邏輯要處理。
座標系。瀏覽器的 clientX、clientY 座標系,以及 Svg 圖自己的座標系,當出現圖的縮放和平移的時候,兩個座標系顯然是不一樣的,那如何作座標系的轉換。
Algorithm。是專門經過幾何、算法來處理可視化的一些問題。好比:當一個節點在同一方向有多條折線連出的時候,如何作路徑的合併以展現起來更美觀,以下
如何計算出一根線到一個圖形的切點,以達到線能夠鏈接圖形非錨點的位置,以下圖
History,主要提供 redo 和 undo 的能力。經過兩個棧來存儲 undos 和 redos,並限制最大長度,得益於 MVVM 的設計模式,能方便的作數據變化的觀測和 Model 驅動 View。
介紹完流程圖編輯器的設計方案,如今來介紹 LogicFlow 的另外一個重要特性,關於拓展性方面的設計。在程序世界中,小到一個 function,一個服務,再到一個開發框架 react,小程序開發框架,大到一個 Chrome 類的應用平臺,都具有本身的可擴展性,這也是軟件發展過程當中要考慮的一種設計選擇。對於 LogicFlow,是解決某個領域問題的開發框架,首先 API 要具有可擴展性;此外 LogicFlow 還提供了視圖層,在 View 部分應該可以讓用戶作二次開發。這兩個擴展的方向肯定以後,最主要的仍是結合業務需求,要能知足當前和將來一段時間內預見的業務場景,但也不能過分設計。
首先,LogicFlow 在面向用戶使用這一層,徹底是基於面向對象的設計模式封裝的,最大的好處是幾乎每一個程序員都熟悉它的使用,使用成本低。經過下面初始化方式即可以瞭解。
const lf = new LogicFlow({ // 實例化 lf 對象
container: document.querySelector('#graph'), // 獲取渲染容器
width: 700,
height: 600,
tool: {
menu: true,
control: true,
},
background: {
color: '#F0F0F0'
},
grid: {
type: 'dot',
size: 20,
},
});
lf.render({ nodes: [], edges: []}); // 在界面上渲染視圖
複製代碼
經過 class LogicFlow
,用戶實例化一次便獲得一個流程圖的實例,狀態也是私有的,各類使用方法經過 lf 的實例調用便可。 關於 API 拓展的設計總結來看:
View 層的拓展性,除了用戶可以定製展示方式以外,最重要的是插件化,由於在流程可視化這條路上,不一樣的業務場景下須要的能力不盡相同,LogicFlow 很難作到支持全部的場景,因此提供好的插拔能力,讓用戶二次開發是比較好的選擇。目前,在 UI 界面上,咱們開放了兩個能力:
基於插件化的思路,咱們已經支持了不一樣的業務系統,並在這個過程當中把一些稍微通用的能力沉澱出來,並封裝到 lf-extension 包,好比用來支持 BPMN 規範的節點。目前 extension 內的拓展主要分了四類:UI 組件、自定義節點、API、adapter。
相信你對 LogicFlow 已經有一個大概的認識了,若是在你負責的業務中也有流程可視化的訴求,而且有較高的拓展性需求,那 LogicFlow 會是一個好的選擇。對於 LogicFlow 技術自己的實現細節、對於類似業務的探討也都歡迎你們來交流。咱們後續會有更多的文章介紹 LogicFlow 在技術設計細節以及咱們對於可視化、業務流程、邏輯編排等領域的一些思考,盡情期待。