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

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


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

這篇技術博客基於軟件工程課程的VisualPytorch之上,代碼在必定程度上參考了http://www.javashuo.com/article/p-ntwdyfrg-du.html這篇博客。css

VisualPytorch項目連接以下:VisualPytorchhtml

前言-爲何要保存流程圖

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

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

如何保存流程圖

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

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

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

在保存時,我採用的是將整個圖分爲兩個數組保存入數據庫中。圖主要由模塊(開始、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的位置。json

保存連線採用的主要方法

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。

相關文章
相關標籤/搜索