在 jsPlumb 上保存和加载流程图

Posted

技术标签:

【中文标题】在 jsPlumb 上保存和加载流程图【英文标题】:Save and load a flowchart on jsPlumb 【发布时间】:2011-09-13 17:00:48 【问题描述】:

在jsPlumb 上保存和加载流程图的最佳方法是什么?

【问题讨论】:

***.com/q/20620719/453767 【参考方案1】:

我通过简单地将所有元素放在一个对象数组中来保存图表,其中每个对象都有目标节点、x、y 坐标

保存时,只需JSON.stringify(whole_object),如果加载,只需JSON.parse() 并手动定位节点并连接它们。

【讨论】:

你能分享一些代码吗?我对如何加载和连接它们感到困惑。 哦.. 那是很久以前的事了,但据我所知,只需通过 JSON.stringify(objectCollection) 保存数据。有关系,位置等。现在当你想加载时,做 JSON.parse(generatedStrnig) 然后手动遍历对象中的每个节点并定位它(使用 CSS)并连接它们(使用 jsPlumb API)。对不起,我不记得确切:)【参考方案2】:

我的解决方案保存并加载 jsPlumb:

function Save() 
    $(".node").resizable("destroy");
    Objs = [];
    $('.node').each(function() 
        Objs.push(id:$(this).attr('id'), html:$(this).html(),left:$(this).css('left'),top:$(this).css('top'),width:$(this).css('width'),height:$(this).css('height'));
    );
    console.log(Objs);



function Load() 
    var s="";
    for(var i in Objs) 
        var o = Objs[i];
        console.log(o);
        s+='<div id="'+ o.id+'" class="node" style="left:'+ o.left+'; top:'+ o.top+'; width:'+ o.width +'; height:'+ o.height +' "> '+ o.html+'</div>';
    
    $('#main').html(s);

UPD 演示:http://jsfiddle.net/Rra6Y/137/

注意:如果演示在 JsFiddle 中不起作用,请确保它指向现有的 jsPlumb 链接(链接在“外部资源”JsFiddle 菜单项中列出

【讨论】:

您好,感谢您提供这些提示。我只是尝试使用 jsplumb 创建一个在线有限状态机设计器并正确保存/加载,我需要传递比您添加到我的数组中的 html 更多的数据。诸如“状态名称”、“connectedTo”等。你知道,实际上是为了保存我的“状态机”,而不仅仅是我的“绘图”。也许你得到了关于如何做到这一点的提示?会很棒! jsfiddle 链接不起作用。无法拖动,也没有创建连接。保存、加载和清除控制台出现错误。【参考方案3】:

我的保存功能不仅仅是保存元素的 x、y 位置及其连接。我还添加了保存连接标签覆盖以及每个元素的自定义文本。您可以根据自己的要求定制此解决方案,但基本上是:

   //save functionality
    function IterateDrawnElements()  //part of save
        var dict = ;
        $('#id_diagram_container').children('div.window').each(function () 
            var pos = $(this).position()
            var diagram_label = $(this).children('div.asset-label').children('div.asset-diagram-label').text()
            if (diagram_label == null || diagram_label == '')
                diagram_label='';
            
            dict[this.id] = [pos.left, pos.top, diagram_label];
        );
        return dict;
    
    function IterateConnections()  //part of save
        var list = [];
        var conns = jsPlumb.getConnections()
        for (var i = 0; i < conns.length; i++) 
            var source = conns[i].source.id;
            var target = conns[i].target.id;
            try
                var label = conns[i].getOverlay("label-overlay").labelText;
            
            catch(err) 
                label = null
            
            //list.push([source, target])
            if (source != null && target != null)
                list.push([source, target, label]);
            ;
        
        return list;
    

当用户点击保存按钮时,我会启动所有这些,向服务器返回一个 ajax 调用,在这种情况下,Django 正在拦截 ajax 请求并将数据保存到数据库中。

//按下保存按钮时调用ajax $save_btn.click(function()

//drawn elements
var d_elements = IterateDrawnElements();
var d_conns = IterateConnections();
var d_name =$('#id_diagram_name').val();

$.ajax(
    url : ".",
    type : "POST",
    dataType: "json",
    data : 
        drawn_elements: JSON.stringify(d_elements),
        conns: JSON.stringify(d_conns),
        diagram_name: d_name,
        csrfmiddlewaretoken: ' csrf_token '
    ,
    success: function (result) 

        if (result.success == true)
            save_status.html(result.message)
        
        //console.log(JSON.stringify(result));
        $save_btn.attr('disabled','disabled');
        if (result.old_name != false)
            //alert()
            $('#id_diagram_name').val(result.old_name)
        
    ,
    error: function(xhr, textStatus, errorThrown) 
        alert("Please report this error: "+errorThrown+xhr.status+xhr.responseText);
    
);
//return false; // always return error?

);

加载所有这些内容更加容易,并且有很多方法可以做到这一点。在 Django 中,您可以直接在模板中生成 html 以及用于连接的 js,或者您可以在 javascript 中为所有内容创建 JSON 对象,然后让 javascript 根据数组绘制所有内容。我为此使用了 jquery。

//js & connections load

var asset_conns = [
    % for conn in diagram_conns  %
    [  conn.source.id ,  conn.target.id , ' conn.name ' ],
    % endfor %
]


// Takes loaded connections and connects them
for (var i = 0; i< asset_conns.length; i++)
    var source = asset_conns[i][0].toString();
    var target = asset_conns[i][1].toString();
    var label = asset_conns[i][2];
    var c = jsPlumb.connect(source: source, target: target, detachable:true, reattach: true );  //on init already know what kind of anchor to use!
    if (label != null && label != 'None')
        c.addOverlay([ "Label",  label: label,  id:"label-overlay" ]);
    


//html right into django template to draw elements, asset element interchangeable terms

% for element in drawn_elements %
    <div id=" element.asset.id " class="window" style="left: element.left px;top: element.top px;background-image: url('% static element.asset.asset_mold.image.url %'); width:  element.asset.asset_mold.image.width px;height:  element.asset.asset_mold.image.height px;">
        <div class="asset-label" id="label- element.asset.id ">
            # element.asset #<a class="lbl-link" id="lbl-link- element.asset.id " href=" element.asset.get_absolute_url "> element.asset </a>
            <div class='asset-diagram-label' id="lbl- element.asset.id ">% if element.asset.diagram_label  % element.asset.diagram_label % endif %</div>
        </div>
        <div class='ep' id="ep- element.asset.id "></div>
    </div>
% endfor %

您可以大大简化此操作,但我的也可以获得元素的背景,以及与周边锚一起使用的元素的标签和形状。此解决方案有效并经过测试。我很快就会在 PyPi 上发布一个开源的 Djago 应用程序。

【讨论】:

【参考方案4】:

我正在使用 YUI。我正在将每个盒子项目的位置保存在表格中。我有一个单独的表来存储项目之间的父子关系,用于确定 jsPlumb 应该绘制的线条。我使用选择过程来确定这一点,其中选择的第一个项目是父项,所有其他项目都是子项。当点击“连接”按钮时,项目的父/子选择被清除。如果您单击选定的父级,我也会切换它 - 它也会清除子级选择。

【讨论】:

【参考方案5】:

我最近写了一篇关于为什么 jsPlumb 没有保存功能(以及我建议你做什么)的博文:

http://jsplumb.tumblr.com/post/11297005239/why-doesnt-jsplumb-offer-a-save-function

...也许有人会觉得它有用。

【讨论】:

人们正在寻找的是一种简单的说法:将此图保存到 xml/json,或者以其他可以轻松解析和映射以更新数据模型的方式保存...这似乎是一个明显的可用性问题。您在此处概述的内容似乎会让我采取许多烦人的额外步骤才能以我想要的方式到达那里。

以上是关于在 jsPlumb 上保存和加载流程图的主要内容,如果未能解决你的问题,请参考以下文章

jsPlumb.getConnections 不工作

基于jsplumb的流程图展示

利用jsplumb和碰撞检测自动生成流程图

JsPlumb流程图没有自连接

使用jsPlumb插件实现动态连线功能

vue+jsPlumb制成的流程图项目