jQuery拖拽连接线

记录一个利用jquery UI 和jquery  jsPlumb插件完成的拖拽连线demo,效果如下:

jQuery拖拽连接线

html及css样式文件:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            *{
                padding:0;
                margin:0;
                box-sizing: border-box;
            }
            #left{
                height:600px;
                width:200px;
                border:1px solid #000;
                float: left;
                margin-left:100px;
                padding:0 10px;
                position:relative;
            }
            #main{
                height:800px;
                width:1000px;
                border:1px solid #000;
                float: left;
                margin-left:100px;
                position:relative;
            }
            .item{
                background: #ffffff;
                height:30px;
                width:178px;
                border:1px solid #5F9EDF;
                margin: 5px 0;
                font: 16px/30px "微软雅黑";
                text-align: center;
                border-radius: 15px;
                cursor: pointer;
            }
            .theGrey{
                background:#ccc!important;
            }
        </style>
    </head>
    <body>
        <div id="left">
            <div class="item" data-index="1">cf_训练_data</div>
            <div class="item" data-index="2">cf_sql取购买行为</div>
            <div class="item" data-index="3">协同过滤etrec_1</div>
            <div class="item" data-index="4">sql整理输出格式</div>
            <div class="item" data-index="5">json-1</div>
            <div class="item" data-index="6">json-2</div>
            <div class="item" data-index="7">sql去重-1</div>
            <div class="item" data-index="8">sql去重-2</div>
            <div class="item" data-index="9">全表统计-1</div>
            <div class="item" data-index="10">全表统计-2</div>
            <div class="item" data-index="11">cf_结果_data</div>
            <div class="item" data-index="12">过滤与映射-1</div>
        </div>
        <div id="main">
        </div>
        <button  onclick="save()">保存</button>
        <br />
        <br />
        <input type="checkbox" id="onOff"/><label for="onOff">不可重复拖拽</label>
    </body>
</html>
 

 

 

用到的js文件:

<script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script>//
<script src="http://www.jq22.com/jquery/jquery-ui-1.11.0.js"></script>
<script src="js/jquery.jsPlumb-1.6.2-min.js" type="text/javascript" charset="utf-8"></script>

 

jquery实现拖拽、克隆、连接:

<script type="text/javascript">
            function deepCopy(p, c) {  //克隆对象
                var c = c || {};  
                for (var i in p) {  
                    if(! p.hasOwnProperty(i)){  
                        continue;  
                    }  
                    if (typeof p[i] === 'object') {  
                        c[i] = (p[i].constructor === Array) ? [] : {};  
                        deepCopy(p[i], c[i]);  
                    } else {  
                        c[i] = p[i];  
                    }  
                }  
                return c;  
            } 
            function save() {
                var connects = [];//存储连线的数组
                var mainArr=[];//存储元素的数组
                $.each(jsPlumb.getAllConnections(), function (idx, connection) {
                    connects.push({
                        ConnectionId: connection.id,
                        start:$(connection.source).attr("data-index"),
                        end:$(connection.target).attr("data-index"),
                        originSign:$(connection.source).attr("data-sign"),
                        destinationSign:$(connection.target).attr("data-sign"),
                    });
                });
                $("#main .item").each(function(){
                    mainArr.push({
                        offset:$(this).position(),
                        text:$(this).text(),
                        index:$(this).attr("data-index"),
                        sign:$(this).attr("data-sign"),
                    });
                });
                console.log(connects);
                console.log(mainArr);
                sessionStorage.setItem("flowsheet",JSON.stringify({"connects":connects,"mainArr":mainArr}));
            }
            jsPlumb.ready(function() {//一定要加,否则你妹的老报错
                var connectorPaintStyle = {//基本连接线样式
                    lineWidth: 1,//连接线宽度
                    strokeStyle: "#989898",//连接线颜色
                    joinstyle: "round",
                    outlineColor: "white",
                    outlineWidth: 0
                };
                var connectorHoverStyle = {// 鼠标悬浮在连接线上的样式
                    lineWidth: 4,
                    strokeStyle: "#989898",
                    outlineColor: "white",
                    outlineWidth: 0,
                };
                var origin = {//起点
                    endpoint: ["Dot", { radius: 8 }],  //端点的形状
                    connectorStyle: connectorPaintStyle,//连接线的颜色,大小样式
                    connectorHoverStyle: connectorHoverStyle,
                    paintStyle: {
                        strokeStyle: "#989898",
                        fillStyle: "transparent",
                        radius: 4,
                        lineWidth: 1
                    },        //端点的颜色样式
//                    anchor: "AutoDefault",
                    isSource: true,    //是否可以拖动(作为连线起点)
                    connector: ["Bezier", { stub: [40, 60], gap: 10, cornerRadius: 5, alwaysRespectStubs: true }],  //连接线的样式种类有[Bezier],[Flowchart],[StateMachine ],[Straight ]
                    isTarget: false,    //是否可以放置(连线终点)
                    maxConnections:-1,    // 设置连接点最多可以连接几条线,-1表示无限大
                    connectorOverlays: [["Arrow", { width: 10, length: 10, location: 1 }]]
                };
                var destination = {//终点
                    endpoint: ["Dot", { radius: 5 }],  //端点的形状
                    connectorStyle: connectorPaintStyle,//连接线的颜色,大小样式
                    connectorHoverStyle: connectorHoverStyle,
                    paintStyle: {fillStyle: "#989898",},        //端点的颜色样式
                    isSource: false,    //是否可以拖动(作为连线起点)
                    connector: ["Bezier", { stub: [40, 60], gap: 10, cornerRadius: 5, alwaysRespectStubs: true }],  //连接线的样式种类有[Bezier],[Flowchart],[StateMachine ],[Straight ]
                    isTarget:true,    //是否可以放置(连线终点)
                    maxConnections:-1,    // 设置连接点最多可以连接几条线,-1表示无限大
                    connectorOverlays: [["Arrow", { width: 10, length: 10, location: 1 }]]
                };
                $("#left").children().draggable({
                    helper: "clone",
                    scope: "ss",
                });
                var elementSign=0;//标志元素唯一性
                $("#main").droppable({
                    scope: "ss",
                    drop: function (event, ui) {//在目标(target)容器上释放鼠标 ,ui.draggable[0]为开始拖拽的元素
                        elementSign++;
                        var left = parseInt(ui.offset.left - $(this).offset().left);
                        var top = parseInt(ui.offset.top - $(this).offset().top);
                        var ele=$('<div class="item" data-sign="'+elementSign+'" data-index="'+$(ui.draggable[0]).attr("data-index")+'" >' + $(ui.helper).html() + '</div>');//$(ui.helper).html()取第一个JQ元素的文本
                        ele.css({"left":left,"top":top,position: "absolute",margin:0});
                        $(this).append(ele);
                        jsPlumb.addEndpoint(ele, { anchors: "BottomCenter" }, origin);//起点
                        jsPlumb.addEndpoint(ele, { anchors: "TopCenter" }, destination);//终点
                        jsPlumb.draggable(ele,{containment: "parent"});//端点可以拖动设置,并且将端点限制在父级内
                        $(ele).draggable({ //设置拖动到main区域中的元素还可以拖拽
                            containment: "parent" //限制拖动不超过父级边框
                        });
                        //禁止重复拖拽
                        if($("#onOff").prop("checked")){
                            $(ui.draggable[0]).addClass("theGrey").draggable("disable"); // 禁止其拖动功能
                        }
                    }
                });
                $("#main").on("mouseenter", ".item", function () {
                    var ele=$('<span>X</span>');
                    ele.css({position:"absolute",left:"160px",top:"-15px"});
                    $(this).append(ele);
                }).on("mouseleave", ".item", function () {
                    $("span").remove();
                }).on("click", "span",function () {
                    if (confirm("确定删除吗?")) {
                        jsPlumb.removeAllEndpoints($(this).parent().attr("id"));
                        var index=$(this).parent().attr("data-index");
                        $(this).parent().remove();
                        $("#left .item").each(function(){
                            if($(this).attr("data-index")==index){
                                $(this).removeClass("theGrey").draggable("enable"); // **其拖动功能
                            }
                        });
                    }
                });
                jsPlumb.bind("click", function (conn, originalEvent) {//点击线段删除
                     if (confirm("确定删除吗?"))
                         jsPlumb.detach(conn);
                   });
                   jsPlumb.bind("connection", function (connInfo, originalEvent) {//自己连自己管控     
                    if (connInfo.connection.sourceId == connInfo.connection.targetId) {      
                        alert("不能连接自己!");     
                        setTimeout(function(){
                            jsPlumb.detach(connInfo.connection);      
                        },100);
                    }   
                });
                   if(sessionStorage.getItem("flowsheet")){//判断是否有保存过
                       var flowsheet=JSON.parse(sessionStorage.getItem("flowsheet"));
                       var mainHTML=""
                       for(var i=0;i<flowsheet.mainArr.length;i++){
                           if(elementSign<flowsheet.mainArr[i].sign){//如果已经保存过,即将标记更新
                               elementSign=flowsheet.mainArr[i].sign;
                           }
                           mainHTML+='<div class="item" data-sign="'+flowsheet.mainArr[i].sign+'"  data-index="'+flowsheet.mainArr[i].index+'" style="left:'+flowsheet.mainArr[i].offset.left+'px;top:'+flowsheet.mainArr[i].offset.top+'px;position:absolute;margin:0" >' + flowsheet.mainArr[i].text + '</div>';
                       };
                       $("#main").append(mainHTML);
                       $("#main .item").each(function(){
                           jsPlumb.addEndpoint(this, { anchors: "BottomCenter" }, deepCopy(origin, {uuid:$(this).attr("data-sign")+"origin"}));//起点
                           jsPlumb.addEndpoint(this, { anchors: "TopCenter" },  deepCopy(destination, {uuid:$(this).attr("data-sign")+"destination"}));//终点
                           jsPlumb.draggable(this,{containment: "parent"});//端点可以拖动设置,并且将端点限制在父级内
                           $(this).draggable({ //设置拖动到main区域中的元素还可以拖拽
                               containment: "parent" //限制拖动不超过父级边框
                           });
                       });
                       //固定连线
                       for(var i=0;i<flowsheet.connects.length;i++){
                           jsPlumb.connect({uuids:[flowsheet.connects[i].originSign+"origin",flowsheet.connects[i].destinationSign+"destination"]});
                       };
                   }
            });
                
        </script>