jsplump动态绘制状态机图

Jsplump dynamically draw state machine diagram

我正在使用jsplumb绘制动态状态机图。单击按钮后,我需要在绘图区域中添加新框并允许用户根据需要定位它。

我没有得到任何适当的易于理解的文档。我尝试了一些东西:

var i=8; 
function AddDiv() {
    var obj = new Date();
    var Div = $('<div/>', {
        'class':'box ui-draggable ui-draggable-handle ui-droppable',
        'id':'box_'+i,
        'html':'BOXESNEW'
    }).appendTo('.statemachine_cont');
    jsPlumb.addEndpoint($(Div), targetEndpoint);
    $(Div).draggable(
    {
        drag: function(){
            jsPlumb.repaint($(this)); // (or) jsPlumb.repaintEverything(); to repaint the connections and endpoints
        //     jsPlumb.addEndpoint($(this));     
        }
    });
    $(Div).addClass('box ui-draggable ui-draggable-handle ui-droppable');
}
var a = $("#a");

//Setting up drop options
var targetDropOptions = {
    activeClass: 'dragActive'
};
//Setting up a Target endPoint
var targetColor = "#BEBEBE";
var targetEndpoint = {
    anchor: "BottomCenter", //Placement of Dot
    endpoint: ["Dot", { radius: 8}], //Other types are rectangle, Image, Blank, Triangle
    paintStyle: { fillStyle: targetColor }, //Line color
    isSource: true, //Starting point of the connector
    // scope: "green dot",
    connectorStyle: { strokeStyle: "#5C96BC", lineWidth: 2 }, // Means Bridge width and bridge color
    connector: ["Bezier"], //Other properties Bezier
    maxConnections: -1, //No upper limit
    isTarget: true, //Means same color is allowed to accept the connection
    dropOptions: targetDropOptions //Means when the drag is started, other terminals will start to highlight
};
jsPlumb.bind("ready", function () {
    //Set up endpoints on the divs
    jsPlumb.addEndpoint($(".box ui-draggable ui-draggable-handle ui-droppable"), targetEndpoint);
    jsPlumb.addEndpoint($(".box ui-draggable ui-draggable-handle ui-droppable"), sourceEndpoint);

    jsPlumb.draggable($(".box ui-draggable ui-draggable-handle ui-droppable"));
    jsPlumb.animate($("#a"), { "left": 50, "top": 100 }, { duration: "slow" });
});

不确定我做的是否正确,我参考了一些可用的在线代码并对其进行了修改。

我的问题是:单击按钮后,我可以添加一个新框,也可以从该框拖动一个连接。但是当我试图拖动那个盒子(即改变它的位置)时,连接不会移动。盒子被移动了,但是我无法移动与盒子的连接。

当我尝试移动新添加的盒子或连接到新盒子的盒子时,两个盒子都可以移动,但连接保持静态并且不会移动。就好像其他盒子被移动一样,它会随着连接一起移动。我添加了一张图片以供参考。

第 1 张图片显示了新添加的框和新连接的显示方式。第二张图片显示了盒子的移动是如何造成问题的。

Div已经是一个jquery对象,不需要再包装了。

选项 1

Div.draggable(
    {
        drag: function(){
           jsPlumb.repaintEverything();
        }
    });

选项 2

jsPlumb.draggable(Div.attr('id'));

以下是我设法让它工作的方法。我修改了我的整个代码

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title> - jsFiddle demo</title>

  <script type='text/javascript' src='js/jquery-1.10.1.js'></script>
  <link rel="stylesheet" type="text/css" href="css/demo-all.css">
  <link rel="stylesheet" type="text/css" href="css/demo.css">
  <script type='text/javascript' src="js/jquery.ui.touch-punch-0.2.2.min.js"></script>
  <script type='text/javascript' src="js/jquery-ui-1.9.2.min.js"></script>
  <script type='text/javascript' src="js/jquery.jsPlumb-1.7.2-min.js"></script>
  <style type='text/css'>
    .hidden { display: none; }
  </style>
<script type='text/javascript'>
$(window).load(function(){
function cloneWindow(instance) {
    var $jspContainer = $("#statemachine-demo"),
        divid = "fromTemplate_" + new Date().getTime().toString()        
        $cloneElement = $("<div class='w'>New Window&nbsp;<div class='ep'></div></div>").attr("id", divid);

    $jspContainer.append($cloneElement);

    instance.draggable(divid);
    instance.makeSource($cloneElement, {
                filter: ".ep", // only supported by jquery
                anchor: "Continuous",
                connector: ["StateMachine", {
                    curviness: 1
                }],
                connectorStyle: {
                    strokeStyle: "#5c96bc",
                    lineWidth: 2,
                    outlineColor: "transparent",
                    outlineWidth: 4
                },
                maxConnections: 10,
                onMaxConnections: function (info, e) {
                    alert("Maximum connections (" + info.maxConnections + ") reached");
                }
            });   

    instance.bind("connection", function (info) {
        info.connection.getOverlay("label").setLabel(info.connection.id);
    });


    instance.makeTarget($cloneElement, { 
        anchor:"Continuous", 
        dropOptions:{ hoverClass:"dragHover" }
        });

}

jsPlumb.ready(function () {

        $("#addwindow").click(function() {
          cloneWindow(instance);
        });
        // setup some defaults for jsPlumb. 
        var instance = jsPlumb.getInstance({
            Endpoint: ["Dot", {
                radius: 2
            }],
            HoverPaintStyle: {
                strokeStyle: "#1e8151",
                lineWidth: 2
            },
            ConnectionOverlays: [
                ["Arrow", {
                    location: 1,
                    id: "arrow",
                    length: 14,
                    foldback: 0.8
                }],
                ["Label", {
                    label: "Drag this and drop it on another element to make a connection.",
                    id: "label",
                    cssClass: "aLabel"
                }]
            ],
            Container: "statemachine-demo"
        });

    jsPlumb.importDefaults({
                filter: ".ep",
                anchor: "Continuous",
                connector: ["StateMachine", {
                    curviness: 1
                }],
                connectorStyle: {
                    strokeStyle: "#5c96bc",
                    lineWidth: 2,
                    outlineColor: "transparent",
                    outlineWidth: 4
                },
                maxConnections: 10,
                dropOptions: {
                    hoverClass: "dragHover"
                }

    });
        var windows = jsPlumb.getSelector(".statemachine-demo .w");

        // initialise draggable elements.  
        instance.draggable(windows);

        // bind a click listener to each connection; the connection is deleted. you could of course
        // just do this: jsPlumb.bind("click", jsPlumb.detach), but I wanted to make it clear what was
        // happening.
        instance.bind("click", function (c) {
            instance.detach(c);
        });

        // bind a connection listener. note that the parameter passed to this function contains more than
        // just the new connection - see the documentation for a full list of what is included in 'info'.
        // this listener sets the connection's internal
        // id as the label overlay's text.
        instance.bind("connection", function (info) {
            info.connection.getOverlay("label").setLabel(info.connection.id);
        });

        // suspend drawing and initialise.
        instance.doWhileSuspended(function () {


            // make each ".ep" div a source and give it some parameters to work with.  here we tell it
            // to use a Continuous anchor and the StateMachine connectors, and also we give it the
            // connector's paint style.  note that in this demo the strokeStyle is dynamically generated,
            // which prevents us from just setting a jsPlumb.Defaults.PaintStyle.  but that is what i
            // would recommend you do. Note also here that we use the 'filter' option to tell jsPlumb
            // which parts of the element should actually respond to a drag start.
            instance.makeSource(windows, {
                filter: ".ep", // only supported by jquery
                anchor: "Continuous",
                connector: ["StateMachine", {
                    curviness: 1
                }],
                connectorStyle: {
                    strokeStyle: "#5c96bc",
                    lineWidth: 2,
                    outlineColor: "transparent",
                    outlineWidth: 4
                },
                maxConnections: 10,
                onMaxConnections: function (info, e) {
                    alert("Maximum connections (" + info.maxConnections + ") reached");
                }
            });


            // initialise all '.w' elements as connection targets.
            instance.makeTarget(windows, {
                dropOptions: {
                    hoverClass: "dragHover"
                },
                anchor: "Continuous"
            });

            // and finally, make a couple of connections
            instance.connect({
                source: "opened",
                target: "phone1"
            });
            instance.connect({
                source: "phone1",
                target: "inperson"
            });
            instance.connect({
                source: "phone1",
                target: "phone1"
            });


        });                          

    });
}); 

</script>


</head>
<body>
  <div class="demo statemachine-demo" id="statemachine-demo" style="border:2px solid;border-radius:25px;">
    <button type="button" id="addwindow">Add Window</button>
    <div class="w" id="opened">BEGIN&nbsp;
        <div class="ep"></div>
    </div>
    <div class="w" id="phone1">PHONE INTERVIEW 1&nbsp;
        <div class="ep"></div>
    </div>
    <div class="w" id="phone2">PHONE INTERVIEW 2&nbsp;
        <div class="ep"></div>
    </div>
    <div class="w" id="inperson">IN PERSON&nbsp;
        <div class="ep"></div>
    </div>
    <div class="w" id="rejected">REJECTED&nbsp;
        <div class="ep"></div>
    </div>
    <div class="w hidden" id="template_newwindow">
        <div class="ep"></div>
    </div>
</div>
</body>
</html>