【技術博客】基於JsPlumb和JQuery-UI的流程圖的保存和再生成


開發組在開發過程中,都不可避免地遇到了一些困難或問題,但都最終想出辦法克服了。我們認為這樣的經驗是有必要記錄下來的,因此就有了【技術博客】。


基於JsPlumb和JQuery-UI的流程圖的保存和再生成

這篇技術博客基於軟件工程課程的VisualPytorch之上,代碼在一定程度上參考了https://www.cnblogs.com/sggx/p/3836432.html這篇博客。

VisualPytorch項目鏈接如下:VisualPytorch

前言-為什么要保存流程圖

對於這樣一個類流程圖或者模型圖,用戶會有保存、查看以及再編輯的需求,僅僅提供讓用戶拖拽連線的功能、讓用戶每次都從頭搭建是會嚴重影響用戶體驗的,因此需要能夠保存模型圖。

這篇博客主要用於提供思路,而非提供整套的解決方案,具體解決方案因人而異。

如何保存流程圖

保存流程圖是兩方面的問題:

(1)選定合適的保存格式

(2)確保保存的信息足夠來還原完整的圖

在保存時,我采用的是將整個圖分為兩個數組保存入數據庫中。圖主要由模塊(開始、reshape層)和連線兩部分組成,因此我選擇將模塊保存為一個json,而連線保存為數組。

保存模塊采用的主要方法

$("#canvas").find(".node").each(function (index, element) {
        var id = $(element).attr('id');
        nets[id] = {
            "name": $(element).attr('name'),
            "attribute": eval('(' + window.localStorage.getItem(id) + ')'),
            "left": $(element).css('left'),
            "top": $(element).css('top')
        }
    });

在畫布中遍歷所有的模塊類,nets對象的標簽為模塊的id,而內容為需要保存的屬性。需要注意的是,left與top屬性必須保存,其相當於x,y坐標,用於還原時定位div的位置。

保存連線采用的主要方法

for (var i = 0; i < conn_list.length; i++) {
        var source_id = conn_list[i]["sourceId"];
        var target_id = conn_list[i]["targetId"];
        var conn = {
            "source": {
                "id": source_id,
                "anchor_position": conn_list[i]["endpoints"][0]["anchor"]["type"]
            },
            "target": {
                "id": target_id,
                "anchor_position": conn_list[i]["endpoints"][1]["anchor"]["type"]
            }
        };
        nets_conn.push(conn);
    }

連線保存需要注意兩個地方,首先是conn_list的獲得,即如何得到目前的所有連線,這里我調用了JsPlumb中現有的接口

conn_list = jsPlumb.getAllConnections()

另一個地方時anchor_position。這里涉及到了JsPlumb的部分,在連線的時候,只有有anchor的地方才可以連線,為了復原整個圖,我們需要記錄下anchor的位置。

如何復原流程圖

如何將保存的數據從數據庫中取出不應該是本博客的內容,不多贅述。先貼上完整代碼

 var structure = eval('(' + net_work["structure"] + ')');
                    var nets = structure['nets'];
                    var nets_conn = structure['nets_conn'];
                    var static_val = structure['static'];
                    var drop_function = $("#canvas").droppable('option', 'drop');
                    var event;
                    jQuery.each(nets, function (id, val) {

                        jsPlumb.ready(function () {
                            var ui = {
                                'offset': {
                                    'left': parseInt(val['left'].split('px')) + $("#canvas").offset().left,
                                    'top': parseInt(val['top'].split('px')) + $("#canvas").offset().top
                                },
                                'draggable': [{
                                    "id": val['name'],
                                    "innerHTML": $("#" + val['name'])[0].innerHTML
                                }],
                                'id': id
                            };
                            drop_function(event, ui);
                        });
                        window.localStorage.setItem(id, JSON.stringify(val['attribute']));
                    });
                    jQuery.each(nets_conn, function (id, val) {
                        jsPlumb.ready(function () {
                            jsPlumb.connect({
                                "source": val['source']['id'],
                                "target": val['target']['id'],
                                "anchors": [val['source']['anchor_position'], val['target']['anchor_position']],
                                "endpoint": ["Dot", {radius: 5}],
                                "paintStyle": {
                                    stroke: "#fc2f49",
                                    strokeWidth: 3,

                                },
                                "maxConnections": -1,
                                "connector": ["Flowchart", {
                                    stub: [40, 60],
                                    gap: 5,
                                    cornerRadius: 5,
                                    alwaysRespectStubs: true
                                }],
                                "overlays": [["Arrow", {width: 10, length: 10, location: 1}]],
                                "connectionsDetachable": true,
                            })
                        });
                    });

代碼看着很多,原理非常簡單,就是把用戶畫圖的操作再用js腳本做一遍。

放置模塊

首先第一點,用戶在拖拽div進入畫布時,畫布為droppable狀態,會觸發JQuery-UI 的drop事件。

$("#canvas").droppable({
        scope: "ss",
        drop: function (event, ui) {
            .......
        }
})

第一段代碼中的

 var drop_function = $("#canvas").droppable('option', 'drop')

drop_function函數就對應了drop事件觸發后執行的代碼塊。

如此一來便很容易理解,只要讓每個被保存的模塊去觸發drop事件即可,參數ui用保存的屬性來自己構造,詳情參照代碼。

重新連線

重新連線部分,直接調用JsPlumb的連線方法

jsPlumb.connect()

即可。

注意我們的anchor要選擇之前保存的anchor。




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM