Stories

Detail Return Return

突破Canvas困境:低成本實現Web端流程圖設計功能之道 - Stories Detail

最新技術資源(建議收藏)
https://www.grapecity.com.cn/resources/

前言

相信大家在職場中經常會用到流程圖,在互聯網行業,繪製流程圖不論在產品的設計階段,還是後期優化業務流程的階段,都有着巨大的價值。事實上,不僅是互聯網行業,流程圖其實廣泛應用於各行各業。

比如説,銀行在辦理開户業務時,會有一套較為複雜的流程,中間不僅有固定的步驟,如審核材料、打印憑證等,還會有一些判斷條件,如金額是否超過20萬、是否需憑密碼支取等,這個時候可以通過一張流程圖來清晰明瞭地展現整個業務流:

再例如在進行新員工培訓時,可能有多個部門之間的協作,那麼用流程圖也可以很好地幫助員工瞭解後續的培訓步驟:

再舉個例子,在互聯網行業中,一個項目上線前需要進行完整的測試,測試分為很多類型,如黑盒、白盒、冒煙測試等,按照步驟進行,還要生成對應的測試報告。如果其中某一步測試不通過,需要通知研發修改bug,並重新測試,下面的流程圖就可以非常清晰地展現研發、產品和測試相互合作的過程:

之所以有這麼多的行業都在使用流程圖,是因為它具備以下幾點好處:

1. 讓複雜的過程易於理解。

2. 方便識別業務瓶頸,改進現有流程。

3. 容易向其他人解釋業務。

而SpreadJS(本公司產品,一款前端在線Excel表格)也支持插入流程圖,但是有時候我們並不想自己去繪製流程圖,而是希望根據某種數據結構自動生成一個流程圖,而這個數據可以在服務端自動拼接好,也可以直接是其他三方服務的數據。將數據發送到前端後,自動生成一個流程圖,如果對流程圖做出一定的修改,數據也跟着變動,這樣流程圖的數據也可以保存下來,方便下次使用。

假定我們目前有一個這樣的數據結構(省略部分數據)。

其中elements數組保存了所有的流程,id為流程的唯一id值;text代表流程框中的文本;type代表是普通流程的矩形框還是決策型的菱形框;process代表當前流程的進展,分為未開始、進行中和已完成,默認為未開始;width和height代表形狀的寬高,可以不寫。

edge數組則包含了各個流程中間的連接關係,表現在流程圖中就是箭頭從source指向target,其中flag代表在決策型流程中的結果。

最終想要在SpreadJS中生成這樣一個流程圖:

那麼如何才能實現這樣的效果呢?我認為大致需要做以下幾個工作:

1. 根據elements的信息,向SpreadJS插入所有流程圖形狀

2. 根據edge的連線關係,將各個形狀擺放到正確的位置

3. 創建形狀之間的連線

4. 添加監聽,當流程發生變化時,動態地改變數據

實現步驟

接下來就講一下以上四個步驟具體如何實現。

1. 根據elements的信息,向SpreadJS插入所有流程圖形狀

這一步比較簡單,無非就是遍歷elements,並向當前的sheet插入形狀:

我們通過數據中的信息來修改shape的樣式,包括寬高以及背景色。

這裏我們可以將id掛在shape上,後續方便通過id找到對應的形狀或者數據model。

另外,讀者可以注意到我在數據model上掛載了兩個函數,分別為next和prev,這是為了方便尋找流程的下一級或者上一級,後續會經常用到這兩個函數。

這樣處理後,SpreadJS中的形狀就已經生成好了:

2. 根據edge的連線關係,將各個形狀擺放到正確的位置

這一步是比較困難的,假設我們的流程圖是由左向右擴展的,那麼橫座標(x方向)的位置是很好確定的,每深入一級,橫座標向右移動即可,困難的在於縱座標(y方向)的位置計算,我這裏拋磚引玉,如果大家有更好的算法,可以在評論區分享\~

大致思路如下:請看下圖的結構,左右兩圖中,B、C兩節點距離A的縱向位置是不同的,這是因為左圖的B節點擁有更多的子節點,而右圖則較少,所以左側在縱向需要拉開更多的距離,以擺放後續的節點。

當然,這裏並不是單指子節點數量的多少,而是要看他們所佔據的高度,也就是兄弟節點的數量。所以在代碼中,我們需要遞歸計算一個節點後續的高度值:

其中hasCountMax值是為了預防節點循環的情況,比如A→B→A,代碼中還有類似的處理。

得到節點的高度值後,就可以計算位置了,這個高度值越大,它離父級節點的縱向距離就越遠,當然這裏還要考慮當前節點佔據兄弟節點的第幾個,以及父級、兄弟節點的高度情況:

最後的代碼可以看到這裏也是一個遞歸計算,需要計算每一個節點下一級的位置。

3. 創建形狀之間的連線

這一步的思路有一點小複雜,但是實現起來比較簡單。

難點主要在於確定連接點的位置。矩形和菱形都有4個連接點,在下圖中,左2連接右2並不是最好的連接方式,我們希望是以下三種方式:左2右1、左3右1、左3右0 ,所以我們就需要根據兩個形狀的位置關係來確定連接點。

這裏要用到一點初高中的數學知識,我們要計算從起始形狀到目標形狀中心位置的連線,與橫軸夾角的正弦值來確定連接點:

這裏一共有12種情況,不做一一贅述。

決策圖的連線還要標明“是”和“否”兩種不同的情況,計算連線的中心點並插入形狀即可:

4. 添加監聽,當流程圖發生變化時,動態地改變數據

因為用户可以隨時拖動流程圖,而流程圖的變化屬性大致有以下幾種:位置、長寬、文字屬性,我們要將他們最新的值記錄下來,方便下次還原。另外,當位置和長寬變化時,連線也會自動更新,我們需要更新上文提到的“是”和“否”的文字的位置,這裏用到了防抖模式以提升性能。

另外,我還在設計器中添加了一些新菜單,可以對流程的狀態進行修改,也可以將流程圖導出為圖片,或打印流程圖的數據model等,感興趣的讀者可以在源碼中自行查看實現方式。

這裏展示一下修改流程圖後,數據同步修改的功能,我們以“換貨”舉例,默認狀態下,換貨的數據是這樣的:

我們通過上方的按鈕調整換貨為已完成,修改文本,並且移動它的位置,改變其寬高後:

可以看到,表示其狀態的process已經從1(進行中)變成了2(已完成),寬高、位置、文本也有相應的變化。

結語:

流程圖是一種非常有用,也很常用的工具,結合SpreadJS,你可以比較方便的實現動態生成流程圖的功能,在這個demo的基礎上,你還可以添加右鍵新增子級、新增兄弟級元素等功能,藉助SpreadJS豐富、開放的Api,你可以非常靈活地實現你要的功能。

最後,希望這篇文章能對你有幫助\~

源碼地址:

https://gcdn.grapecity.com.cn/forum.php?mod=attachment&aid=Mj...

擴展鏈接:

Spring Boot框架下實現Excel服務端導入導出

項目實戰:在線報價採購系統(React +SpreadJS+Echarts)

Svelte 框架結合 SpreadJS 實現純前端類 Excel 在線報表設計

user avatar u_15591470 Avatar kongsq Avatar qifengliao_5e7f5b20ee3bd Avatar shanejix Avatar amap_tech Avatar delia_5a38831addb7b Avatar russell221 Avatar stephentian Avatar feibendemaojin Avatar danxiaodezixingche Avatar zlt2000 Avatar ivorysql_xiaozhuli Avatar
Favorites 17 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.