保存和加载jsPlumb流程图,包括精确的锚点和连接。

22

这是我正在构建的流程图编辑器的 jsFiddle 示例。

使用“添加决策”+“添加任务”,连接和移动元素,可以轻松创建如下示例。

Example flowchart - user configured

现在是困难的部分:我想要能够保存和加载确切的流程图。为此,我基于 Stackoverflow 上的一个类似帖子开始了工作。

为此,我添加了“保存”和“加载”按钮,将流程图导出/导入 JSON(在 jsFiddle 中保存后以文本形式显示-相同的文本形式可用于加载)。

保存函数:

function saveFlowchart(){
            var nodes = []
            $(".node").each(function (idx, elem) {
            var $elem = $(elem);
            var endpoints = jsPlumb.getEndpoints($elem.attr('id'));
            console.log('endpoints of '+$elem.attr('id'));
            console.log(endpoints);
                nodes.push({
                    blockId: $elem.attr('id'),
                    nodetype: $elem.attr('data-nodetype'),
                    positionX: parseInt($elem.css("left"), 10),
                    positionY: parseInt($elem.css("top"), 10)
                });
            });
            var connections = [];
            $.each(jsPlumb.getConnections(), function (idx, connection) {
                connections.push({
                    connectionId: connection.id,
                    pageSourceId: connection.sourceId,
                    pageTargetId: connection.targetId
                });
            });

            var flowChart = {};
            flowChart.nodes = nodes;
            flowChart.connections = connections;
            flowChart.numberOfElements = numberOfElements;

            var flowChartJson = JSON.stringify(flowChart);
            //console.log(flowChartJson);

            $('#jsonOutput').val(flowChartJson);
        }

上述示例的生成JSON:

{"nodes":[{"blockId":"startpoint","nodetype":"startpoint","positionX":273,"positionY":8},{"blockId":"endpoint","nodetype":"endpoint","positionX":310,"positionY":385},{"blockId":"taskcontainer1","nodetype":"task","positionX":381,"positionY":208},{"blockId":"decisioncontainer2","nodetype":"decision","positionX":261,"positionY":103}],"connections":[{"connectionId":"con_18","pageSourceId":"decisioncontainer2","pageTargetId":"taskcontainer1"},{"connectionId":"con_25","pageSourceId":"taskcontainer1","pageTargetId":"endpoint"},{"connectionId":"con_32","pageSourceId":"decisioncontainer2","pageTargetId":"endpoint"},{"connectionId":"con_46","pageSourceId":"startpoint","pageTargetId":"decisioncontainer2"}],"numberOfElements":2}

通过这个,我能够保存元素位置和部分连接信息。下面是加载函数

function loadFlowchart(){
            var flowChartJson = $('#jsonOutput').val();
            var flowChart = JSON.parse(flowChartJson);
            var nodes = flowChart.nodes;
            $.each(nodes, function( index, elem ) {
                if(elem.nodetype === 'startpoint'){
                    repositionElement('startpoint', elem.positionX, elem.positionY);
                }else if(elem.nodetype === 'endpoint'){
                    repositionElement('endpoint', elem.positionX, elem.positionY);
                }else if(elem.nodetype === 'task'){
                    var id = addTask(elem.blockId);
                    repositionElement(id, elem.positionX, elem.positionY);
                }else if(elem.nodetype === 'decision'){
                    var id = addDecision(elem.blockId);
                    repositionElement(id, elem.positionX, elem.positionY);
                }else{

                }
            });

            var connections = flowChart.connections;
            $.each(connections, function( index, elem ) {
                 var connection1 = jsPlumb.connect({
                    source: elem.pageSourceId,
                    target: elem.pageTargetId,
                    anchors: ["BottomCenter", [0.75, 0, 0, -1]]

                });
            });

            numberOfElements = flowChart.numberOfElements;
        }

然而,锚点和连接的确切位置已经丢失。再次举个例子,在删除元素后加载导出的JSON后的结果:

加载JSON后的流程图

这并不是什么大惊小怪的事情,因为我还没有存储这些信息。但是我现在卡在了这一步。

我的问题是:我需要存储哪些关于锚点/连接器位置的信息来设计整个流程图,并且如何从jsPlumb中提取它(然后再次加载)?

1个回答

26

查看此JSFiddle以获取解决方案。

您需要按照以下方式保存锚点详细信息。这符合这里定义的锚点表示法。请注意双重嵌套以避免JQuery在地图上自动展开。

    $.each(jsPlumb.getConnections(), function (idx, connection) {
      connections.push({
      connectionId: connection.id,
      pageSourceId: connection.sourceId,
      pageTargetId: connection.targetId,
      anchors: $.map(connection.endpoints, function(endpoint) {

        return [[endpoint.anchor.x, 
        endpoint.anchor.y, 
        endpoint.anchor.orientation[0], 
        endpoint.anchor.orientation[1],
        endpoint.anchor.offsets[0],
        endpoint.anchor.offsets[1]]];

      })
    });
  });

...并按照以下方式加载它们:

    $.each(connections, function( index, elem ) {
     var connection1 = jsPlumb.connect({
      source: elem.pageSourceId,
      target: elem.pageTargetId,
      anchors: elem.anchors
    });

  });

请注意,该解决方案不保留端点细节,包括端点的形状和类型。它仅保留锚点细节,正如您所要求的那样。


1
非常感谢,完美运作。 我接受这个答案并快速编辑了一下,包括端点的绘制样式,以便格式也得以保留。 - hbit
为什么保存和加载时,未附加的副本也会出现? - radtek
@hbit,我找不到你为保存和恢复端点的绘制和样式所做的编辑。你能分享一下代码吗?我尝试过了,但我想我可能漏掉了什么。 - coding_idiot
在所有这些之后,我又遇到了另一个问题,绑定函数与这些已加载的连接一起工作!!!但是绑定函数与新创建的连接一起工作。???请帮帮我。 - Nisfan
1
如果有一个好用的 jsPlumb.jsonify() 函数就太棒了,但这是下一个最好的选择。 - StockB
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接