mxGraph绘图拆分重叠的节点连接线(仅组节点有效)

html部分

组节点坐标随机生成

<!DOCTYPE html>
<html>
<head>
    <title>组节点</title>
    <meta charset="UTF-8">
    <script type="text/javascript">
        mxBasePath = '../src';
    </script>
    <script type="text/javascript" src="../src/js/mxClient.js"></script>

    <script type="text/javascript">
        function main(container)
        {
            if (!mxClient.isBrowserSupported())
            {
                mxUtils.error('Browser is not supported!', 200, false);
            }
            else
            {
                var nodeWidth = 160;
                var nodeHeight = 130;
                var minMargin = 150;
                var defaultRadiu = Math.max(nodeWidth / 2, nodeHeight / 2);
                var width = document.getElementById('graphContainer').offsetWidth;
                var _w = width-10;
                var defaultVertexStyleStr = 'fillColor=#339966;labelBorderColor=none;fontColor=#FFFFFF;labelBackgroundColor=none;strokeColor=none';
                var defaultEdgeStyleStr = 'fontColor=#000;';
                var levelTemp1 = ['a1','a2','a3'];
                var levelTemp2 = ['b1','b2','b3'];
                var topSpace = 90;
                var prefixStr = 'nodeid';
                var nodeData = [];

                function RandomCoord(obj){
                    this.dWidth = obj.width;
                    this.dHeight = obj.height;

                    this.fix = obj.fix || false;
                    this.minMargin = obj.minMargin;
                    this.minRadius = obj.minRadius || 30;
                    this.total = obj.total || 10;
                    this.coordArray = [];
                }
                RandomCoord.prototype.check = function(x,y,r){
                    return !(x+r>this.dWidth || x-r<0||y+r>this.dHeight||y-r<0||x<r);
                };
                RandomCoord.prototype.getR = function(x,y){
                    if(this.coordArray.length == 0){
                        return true;
                    }
                    var lenArr = this.coordArray.map(function(c){
                        let _x = c.x-x;
                        let _y = c.y-y;
                        return Math.floor(Math.sqrt(Math.pow(_x, 2) + Math.pow(_y, 2))) - c.r;
                    });
                    var minCircleLen = Math.min.apply(null, lenArr);
                    let tempR = minCircleLen - this.minMargin;
                    let bool = tempR >= this.minRadius;
                    if(bool){
                        return tempR;
                    }else{
                        return false;
                    }
                }
                RandomCoord.prototype.createOneCircle = function () {
                    let x, y, r;
                    let createCircleTimes = 0;
                    while (true){
                        createCircleTimes ++;
                        x = Math.floor(Math.random()*this.dWidth);
                        y = Math.floor(Math.random()*this.dHeight);
                        let TR = this.getR(x, y);
                        if(!TR){
                            continue;
                        }else{
                            r = defaultRadiu;
                        }
                        if(this.check(x,y,r) || createCircleTimes > 200){
                            if(this.total == 1){
                                this.coordArray.push({x:x,y:y,r:r});
                            }
                            break;
                        }
                    }
                    this.check(x,y,r) && this.coordArray.push({x:x,y:y,r:r});
                }
                RandomCoord.prototype.init = function(){
                    let n = 0;
                    let that = this;
                    while(this.coordArray.length < this.total){
                        this.coordArray = [];
                        let i=0;
                        while(this.coordArray.length < this.total){
                            this.createOneCircle();
                            i++;
                            if(i>=100){
                                break;
                            }
                        }
                        n++;
                        if(n>=100){
                            break;
                        }
                    }
                }
                RandomCoord.prototype.getPositionCoords = function(){
                    return this.coordArray;
                };

                var _n = [];
                var _tempStatusArr= [];
                var totalAttach = 3;
                var linesData = [];
                var graphType = 1;   // 1-折线   2-直线

                var model = new mxGraphModel();
                var graph = new mxGraph(document.getElementById('graphContainer'), model);
                //                节点是否可以改变大小
                graph.setCellsResizable(false);
                //                是否拖动节点
                mxGraphHandler.prototype.setMoveEnabled(true);
                //                是否可以移动连线
                graph.setCellsLocked(false);
                graph.setConnectable(false);
                //                整体移动
                graph.setPanning(true);
                graph.panningHandler.useLeftButtonForPanning = true;
                graph.setHtmlLabels(true);
                graph.setTooltips(true);

                //                设置两个节点是否可以建立多个连接
                graph.setMultigraph(true);
                graph.foldingEnabled = false;  // 关闭组折叠功能
                graph.isSelectedEdge(false);   // 添加自定义设置,线不可选中且不可移动

                if(graphType == 1){
                    graph.lineType = 'brokenLine';
                }else{
                    graph.lineType = 'straightLine';
                }         

                graph.isCellFoldable = function(cell, collapse){
                    var childCount = this.model.getChildCount(cell);
                    for(var i=0;i<childCount;i++){
                        var child = this.model.getChildAt(cell, i);
                        var geo = this.getCellGeometry(child);
                        if(geo != null && geo.relative){
                            return false;
                        }
                    }
                    return childCount > 0;
                };

                function getRelativePosition(state, dx, dy){
                    if(state != null){
                        var model = graph.getModel();
                        var geo = model.getGeometry(state.cell);

                        if(geo != null && geo.relative && !model.isEdge(state.cell)){
                            var parent = model.getParent(state.cell);
                            if(model.isVertex(parent)){
                                var pstate = graph.view.getState(parent);
                                if(pstate!=null){
                                    var x = state.x+dx;
                                    var y = state.y+dy;

                                    x = (x-pstate.x)/pstate.width;
                                    y = (y-pstate.y)/pstate.height;

                                    var scaleW = geo.width / pstate.width;
                                    var scaleH = geo.height / pstate.height;
                                    if(x<=0){x=0}
                                    if(y<=0){y=0}
                                    if(x>=1||(x+scaleW>=1)){x=1}
                                    if(y>=1||(y+scaleH>=1)){y=1}

                                    return new mxPoint(x, y);
                                }
                            }
                        }
                    }
                    return null;
                }

                graph.translateCell = function(cell, dx, dy){
                    var rel = getRelativePosition(this.view.getState(cell), dx*graph.view.scale, dy*graph.view.scale);
                    if(rel != null){
                        var geo = this.model.getGeometry(cell);
                        if(geo != null && geo.relative){
                            geo = geo.clone();
                            geo.x = rel.x;
                            geo.y = rel.y;
                            //  重置x
                            geo.offset.x = 0;
                            if(rel.x == 1){
                                geo.offset.x -= geo.width;
                            }
                            // 重置y
                            geo.offset.y = 0;
                            if(rel.y == 1){
                                geo.offset.y -= geo.height;
                            }
                            this.model.setGeometry(cell, geo);
                        }
                    }
                    else{
                        mxGraph.prototype.translateCell.apply(this, arguments);
                    }
                };

                graph.graphHandler.getDelta = function(me){
                    var point = mxUtils.convertPoint(this.graph.container, me.getX(), me.getY());
                    var delta = new mxPoint(point.x - this.first.x, point.y - this.first.y);
                    return delta;
                };

                graph.graphHandler.shouldRemoveCellsFromParent = function (parent, cells, evt) {
                    console.log(cells);
                    return cells.length == 0&&!cells[0].geometry.relative&&mxGraphHandler.prototype.shouldRemoveCellsFromParent.apply(this, arguments);
                };

                var parent = graph.getDefaultParent();

                var layout = new mxCustomEdgeLayout(graph);
                var layoutMgr = new mxLayoutManager(graph);

                layoutMgr.getLayout = function(cell){
                    if(cell.getChildCount() > 0){
                        return layout;
                    }
                };

                var style = graph.getStylesheet().getDefaultEdgeStyle();
                //                折线
                if(graphType == 1){
                    style[mxConstants.STYLE_ROUNDED] = true; // false:直角   true:圆角
                    style[mxConstants.STYLE_EDGE] = mxEdgeStyle.BlineConnector;
                    graph.alternateEdgeStyle = 'elbow=vertical';
                }else{  // 直线
                    style[mxConstants.STYLE_EDGE] = mxEdgeStyle.straightLineConnector;
                }

                var nodelistData = [
                    {
                        id:'b1',text:'食品',x:0,y:0,width:0,height:0,level:1,parents:parent.id,
                        parentID:null,childs:[
                            {id:'n11',text:'苹果',x:0,y:0,width:nodeWidth,height:nodeHeight,parentID:'b1',level:2},
                            {id:'n12',text:'草莓',x:0,y:0,width:nodeWidth,height:nodeHeight,parentID:'b1',level:2},
                            {id:'n13',text:'菠萝',x:0,y:0,width:nodeWidth,height:nodeHeight,parentID:'b1',level:2},
                        ]
                    },
                    {
                        id:'b2',text:'家具',x:0,y:0,width:0,height:0,level:1,parents:parent.id,
                        parentID:null,childs:[
                            {id:'n21',text:'柜子',x:0,y:0,width:nodeWidth,height:nodeHeight,parentID:'b2',level:2},
                            {id:'n22',text:'沙发',x:0,y:0,width:nodeWidth,height:nodeHeight,parentID:'b2',level:2},
                            {id:'n23',text:'躺椅',x:0,y:0,width:nodeWidth,height:nodeHeight,parentID:'b2',level:2},
                        ]
                    },
                    {
                        id:'b3',text:'家电',x:0,y:0,width:0,height:0,level:1,parents:parent.id,
                        parentID:null,childs:[
                            {id:'n31',text:'冰箱',x:0,y:0,width:nodeWidth,height:nodeHeight,parentID:'b3',level:2},
                            {id:'n32',text:'洗衣机',x:0,y:0,width:nodeWidth,height:nodeHeight,parentID:'b3',level:2},
                            {id:'n33',text:'空调',x:0,y:0,width:nodeWidth,height:nodeHeight,parentID:'b3',level:2},
                        ]
                    }
                ];
                for(var i=0;i<nodelistData.length;i++){
                    var totalNode = nodelistData[i].childs.length;
                    var tempFun = null;
                    if(totalNode > 0){
                        var height = Math.ceil(Math.sqrt(totalNode)*(Math.sqrt(defaultRadiu)*Math.sqrt(totalNode))*Math.sqrt(minMargin));
                        tempFun = new RandomCoord({total: totalNode, minMargin:minMargin, height:height, width:_w-100-defaultRadiu});
                        tempFun.init();
                        var tempCoords = tempFun.getPositionCoords();
                        for(var c = 0;c<totalNode;c++){
                            nodelistData[i].childs[c].x = tempCoords[c].x;
                            nodelistData[i].childs[c].y = tempCoords[c].y;
                        }
                    }
                }
                for(var j=0;j<nodelistData.length;j++){
                    nodeData.push(nodelistData[j]);
                    if(nodelistData[j].childs.length > 0){
                        for(var k=0;k<nodelistData[j].childs.length;k++){
                            nodeData.push(nodelistData[j].childs[k]);
                        }
                    }
                }

                linesData = [
                    {originalId: prefixStr+'n11', targetId:prefixStr+'n31', id: 'l1', text:'苹果-l1'},
                    {originalId: prefixStr+'n12', targetId:prefixStr+'n31', id: 'l2', text:'草莓-l2'},
                    {originalId: prefixStr+'n13', targetId:prefixStr+'n31', id: 'l3', text:'菠萝-l3'},
                    {originalId: prefixStr+'n22', targetId:prefixStr+'n32', id: 'l4', text:'沙发+洗衣机'},
                ];

                function createNodeItem(arr){
                    if(!arr)return;
                    var arrLen = arr.length;
                    for(var i=0;i<arrLen;i++){
                        var doc = mxUtils.createXmlDocument();
                        var itemElem = doc.createElement('relation');
                        itemElem.setAttribute('text', arr[i].text);
                        itemElem.setAttribute('id', arr[i].id);
                        itemElem.setAttribute('level', arr[i].level);
                        itemElem.setAttribute('parents', arr[i].parents);
                        itemElem.setAttribute('parentID', arr[i].parentID);
                        itemElem.setAttribute('isSelected', arr[i].level == 2 ?'true':'false');

                        if(arr[i].parentID == null){
                            arr[i].width = _w;
                            var layer0StyleStr = '';
                            if(arr[i].id == 'b1'){
                                layer0StyleStr = layer0StyleStr+'fillColor=none;';
                                arr[i].preNode = null;
                            }else if(arr[i].id == 'b2'){
                                layer0StyleStr = layer0StyleStr+'fillColor=none;';
                                arr[i].preNode = 'b1';
                            }else if(arr[i].id == 'b3'){
                                layer0StyleStr = layer0StyleStr+'fillColor=none;';
                                arr[i].preNode = 'b2';
                            }

                            if(arr[i].childs.length == 0){
                                arr[i].height = 200;
                            }

                            if(i==0){
                                var vertex = graph.insertVertex(
                                        parent, arr[i].id, itemElem, 0, 0,
                                        arr[i].width, arr[i].height,
                                        layer0StyleStr+'align=left;strokeColor=#cccccc;'
                                );
                            }else {
                                var _previousId = levelTemp2[levelTemp2.indexOf(arr[i].id) - 1];
                                model.getCell(_previousId).geometry.height = model.getCell(_previousId).geometry.height + 90;
                                var _y = model.getCell(_previousId).geometry.y + model.getCell(_previousId).geometry.height + 20;

                                var vertex = graph.insertVertex(
                                        parent, arr[i].id, itemElem, 0, _y,
                                        arr[i].width, arr[i].height,
                                        layer0StyleStr+'align=left;strokeColor=#cccccc;'
                                );
                            }
                            _n.push(vertex);
                        }else{
                            itemElem.setAttribute('parents', parent.id);

                            var node = graph.insertVertex(
                                model.getCell(arr[i].parentID), prefixStr+arr[i].id,
                                itemElem,
                                arr[i].x || 0,
                                arr[i].y || 0,
                                arr[i].width || nodeWidth,
                                arr[i].height || nodeHeight,
                                defaultVertexStyleStr+(arr[i].style || '')        
                            );
                            _n.push(node);
                        }
                    }

                    createLinks(linesData);
                }
                function createLinks(arr){
                    var linkArrLen = arr.length;
                    var tempObj1 = {};
                    // 统计单个节点的线的总数
                    for(var i=0;i<linkArrLen;i++){
                        // 折线
                        if(graphType == 1){
                            if(tempObj1[arr[i].originalId] != undefined && tempObj1[arr[i].originalId].totalEdges != undefined){
                                tempObj1[arr[i].originalId].totalEdges ++;
                            }else{
                                tempObj1[arr[i].originalId] = {};
                                tempObj1[arr[i].originalId].totalEdges = 1;
                            }
                        }

                        if(tempObj1[arr[i].targetId] != undefined && tempObj1[arr[i].targetId].totalEdges!=undefined){
                             tempObj1[arr[i].targetId].totalEdges ++;
                        }else{
                            tempObj1[arr[i].targetId] = {};
                            tempObj1[arr[i].targetId].totalEdges = 1;
                        }
                    }
                    // 计算space
                    for(var k in tempObj1){
                        var tempCell = model.getCell(k);
                        var cellGeo = model.getGeometry(tempCell);
                        var cellGeoClone = cellGeo.clone();

                        for(var c in tempObj1[k]){
                            cellGeoClone[c] = tempObj1[k][c];
                            cellGeoClone.space = Math.ceil(Math.min(cellGeoClone.height, cellGeoClone.width) / (cellGeoClone[c] + totalAttach));
                            model.setGeometry(tempCell, cellGeoClone);
                        }
                    }

                    for(var j=0;j<linkArrLen;j++){
                        var doc = mxUtils.createXmlDocument();
                        var itemLink = doc.createElement('relation');
                        itemLink.setAttribute('text', arr[j].text);
                        var linkItem = graph.insertEdge(
                            parent, arr[j].id, arr[j].text,
                            model.getCell(arr[j].originalId),
                            model.getCell(arr[j].targetId), ''
                        );
                    }
                }

                // 修改节点显示的信息
//                 if(graph.lineType == 1){
                     graph.convertValueToString = function(cell){
                         if(cell.vertex){
                             var div = document.createElement('div');
                             if(mxUtils.isNode(cell.value)){
                                 var text = cell.getAttribute('text');
                                 var level = cell.getAttribute('level');

                                 if(level == 1){
                                     div.innerHTML = "<div class='celllabelcon reset-celllabelcon'>"+text+"</div>";
                                 }else{
                                     div.innerHTML = "<div class='celllabelcon'>"+text+"</div>";
                                 }
                                 return div;
                             }
                         }
                         return cell.value;
                     }
//                 }

                // 鼠标移入时显示节点和与线label
                graph.getTooltip=function(state){
                    var cell = state.cell;
                    var model = this.getModel();
                    var text = cell.getAttribute('text');

                    if(model.isEdge(cell)){
                        if(text != 'null' && text != undefined){
                            return '<div style="color:#db3338">'+text+'</div>';
                        }
                    }
                }

                window.cellMoved = false;
                graph.getModel().beginUpdate();

                try{
                    createNodeItem(nodeData);
                }finally{
                    graph.cellsOrdered(_n, null);
                    graph.getModel().endUpdate();
                }

                var edges = [],highlightFnArr = [],highlight=null;
                graph.addListener(mxEvent.FIRE_MOUSE_EVENT, function(sender, evt){
                    var evtName = evt.getProperty('eventName');
                    var me = evt.getProperty('event');

                    if(evtName==mxEvent.MOUSE_DOWN && me.state != undefined){
                        var cell = me.state.cell;

                        if(cell.children){
                            removedHighlight();  // 删除高亮
                        }
                        if(cell!=null&&cell!=undefined&&model.isVertex(cell)&&!cell.children){
                            removedHighlight();
                            edges = cell.edges;
                            setHighlight(edges);

                            if(graphType == 1){
                                window.cellMoved = true;   // 判断当前是否有移动的节点,true:是    false:否

                                var edgelist = cell.edges;
                                if(edgelist&&edgelist.length > 0){
                                    var len = edgelist.length;
                                    for(var i=0;i<len;i++){
                                        var _e = edgelist[i];
                                        var _eGeo = model.getGeometry(_e);
                                        var _eGeoClone = _eGeo.clone();
                                        var src = graph.view.getVisibleTerminal(_e, true);
                                        var trg = graph.view.getVisibleTerminal(_e, false);
                                        var srcGeo = model.getGeometry(src);
                                        var trgGeo = model.getGeometry(trg);
                                        var srcGeoClone = srcGeo.clone();
                                        var trgGeoClone = trgGeo.clone();

                                        // 先删除节点上的统计数
                                        deleteEdgeGeometry(src, srcGeoClone, false, _eGeoClone);
                                        // 先删除节点上的统计数
                                        deleteEdgeGeometry(trg, trgGeoClone, false, _eGeoClone);
                                        // 再删除线上的统计数
                                        deleteEdgeGeometry(_e, _eGeoClone, true);
                                    }
                                }
                            }
                        }
                    }
                });
                // 设置线高亮
                function setHighlight(arr){
                    if(!arr)return;
                    for(var i =0;i<arr.length;i++){
                        var  edge = arr[i];
                        highlightFn(edge, graph);
                    }
                }
                // 删除线高亮
                function removedHighlight(){
                    if(highlightFnArr.length > 0){
                        for(var j=0;j<highlightFnArr.length;j++){
                            highlightFnArr[j].destroy();
                            highlight=null;
                        }
                        highlightFnArr = [];
                        edges = [];
                    }
                }
                function highlightFn(cell, graph){
                    highlight = new mxCellHighlight(graph, '#00FF00', 1);
                    highlight.spacing = -1;
                    highlight.highlight(graph.view.getState(graph.model.getCell(cell.id)));
                    highlightFnArr.push(highlight);
                }

                if(graphType == 1){
                    graph.addListener(mxEvent.CELLS_MOVED, function(cells, evt){
                        var cell = evt.getProperty('cells')[0];
                        var dx = evt.getProperty('dx');
                        var dy = evt.getProperty('dy');
                        window.cellMoved = true; 
                        delete window.edgesLabelMap;

                        if(model.isVertex(cell)){
                            var edgelist = cell.edges;
                            if(edgelist&&edgelist.length>0){
                                for(var i=0;i<edgelist.length;i++){
                                    var _e = edgelist[i];
                                    var _eGeo = model.getGeometry(_e);
                                    var _eGeoClone = _eGeo.clone();

                                    var src = graph.view.getVisibleTerminal(_e, true);
                                    var trg = graph.view.getVisibleTerminal(_e, false);
                                    var srcGeo = model.getGeometry(src);
                                    var trgGeo = model.getGeometry(trg);
                                    var srcGeoClone = srcGeo.clone();
                                    var trgGeoClone = trgGeo.clone();

                                    // 先删除节点上的统计数
                                    deleteEdgeGeometry(src, srcGeoClone, false, _eGeoClone);
                                    // 先删除节点上的统计数
                                    deleteEdgeGeometry(trg, trgGeoClone, false, _eGeoClone);
                                    // 再删除线上的统计数
                                    deleteEdgeGeometry(_e, _eGeoClone, true);
                                }
                            }
                        }
                    });
                    // 删除已存在的统计线数据
                    function deleteEdgeGeometry(_e, _eGeoClone, flag, edgeGeo){
                        if(flag){
                            if(_eGeoClone.left){
                                delete _eGeoClone.left;
                            }
                            if(_eGeoClone.right){
                                delete _eGeoClone.right;
                            }
                        }else{
                            if(_eGeoClone.left == edgeGeo.left){
                                delete _eGeoClone.left;
                            }
                            if(_eGeoClone.right == edgeGeo.right){
                                delete _eGeoClone.right;
                            }
                        }
                        model.setGeometry(_e, _eGeoClone);
                    }
                }else{
                    graph.addListener(mxEvent.CELLS_MOVED, function(cells, evt){
                        delete window.edgesLabelCountMap;
                    });
                }

            }
        }
    </script>
</head>

<body onload="main(document.getElementById('graphContainer'))">

<div id="graphContainer"
     style="position:relative;overflow:hidden;width:100%;height:100%;background:url('editors/images/grid.gif');cursor:default;">
</div>
</body>
</html>

以下为需要修改的js部分

路径:javascript\src\js\mxClient.js

// 引入自定义的线构造函数
mxClient.include(mxClient.basePath+'/js/layout/mxCustomEdgeLayout.js');

路径:javascript\src\js\layout\mxCustomEdgeLayout.js(此文件为新增文件)

function mxCustomEdgeLayout(graph)
{
	mxGraphLayout.call(this, graph);
};
mxCustomEdgeLayout.prototype = new mxGraphLayout();
mxCustomEdgeLayout.prototype.constructor = mxCustomEdgeLayout;
mxCustomEdgeLayout.prototype.spacing = 12;
mxCustomEdgeLayout.prototype.execute = function(parent)
{
	var lookup = this.findParallels(parent);
	
	this.graph.model.beginUpdate();	
	try
	{
		for (var i in lookup)
		{
			var parallels = lookup[i];
			this.layout(parallels);
		}
	}
	finally
	{
		this.graph.model.endUpdate();
	}
};
mxCustomEdgeLayout.prototype.findParallels = function(parent)
{
	var model = this.graph.getModel();
	var lookup = [];
	var childCount = model.getChildCount(parent);
	
	for (var i = 0; i < childCount; i++)
	{
		var child = model.getChildAt(parent, i);
		
		if (!this.isEdgeIgnored(child))
		{
			var id = this.getEdgeId(child);
			
			if (id != null)
			{
				if (lookup[id] == null)
				{
					lookup[id] = [];
				}
				
				lookup[id].push(child);
			}
		}
	}
	
	return lookup;
};
mxCustomEdgeLayout.prototype.getEdgeId = function(edge)
{
	var view = this.graph.getView();
	
	var src = view.getVisibleTerminal(edge, true);
	var trg = view.getVisibleTerminal(edge, false);

	if (src != null && trg != null)
	{
		src = mxObjectIdentity.get(src);
		trg = mxObjectIdentity.get(trg);
		
		return (src > trg) ? trg + '-' + src : src + '-' + trg;
	}
	
	return null;
};
mxCustomEdgeLayout.prototype.layout = function(parallels)
{
	var edge = parallels[0];
	var view = this.graph.getView();
	var model = this.graph.getModel();
	var src = model.getGeometry(view.getVisibleTerminal(edge, true));
	var trg = model.getGeometry(view.getVisibleTerminal(edge, false));

	var srcCell = view.getVisibleTerminal(edge,true);
	var trgCell = view.getVisibleTerminal(edge,false);

	var srcParent = model.getCell(srcCell.parent.id);
	var trgParent = model.getCell(trgCell.parent.id);

	var srcParentGeo = model.getGeometry(srcParent);
	var trgParentGeo = model.getGeometry(trgParent);

	if(srcCell.parent.id != trgCell.parent.id){
		src.x = src.x + srcParentGeo.x;
		src.y = src.y + srcParentGeo.y;

		trg.x = trg.x + trgParentGeo.x;
		trg.y = trg.y + trgParentGeo.y;
	}
	
	if (src == trg)
	{
		var x0 = src.x + src.width + this.spacing;
		var y0 = src.y + src.height / 2;

		for (var i = 0; i < parallels.length; i++)
		{
			this.route(parallels[i], x0, y0);
			x0 += this.spacing;
		}
	}
	else if (src != null && trg != null)
	{
		var scx = src.x + src.width / 2;
		var scy = src.y + src.height / 2;
		
		var tcx = trg.x + trg.width / 2;
		var tcy = trg.y + trg.height / 2;
		
		var dx = tcx - scx;
		var dy = tcy - scy;

		var len = Math.sqrt(dx * dx + dy * dy);    // 对角线
		
		if (len > 0)
		{
			var x0 = scx + dx / 2;
			var y0 = scy + dy / 2;
			
			var nx = dy * this.spacing / len;
			var ny = dx * this.spacing / len;
			
			x0 += nx * (parallels.length - 1) / 2;
			y0 -= ny * (parallels.length - 1) / 2;

			// 当线超出父级宽度或小于0时的异常处理
			if(x0 > 0){
				var _space = (parallels.length -1)*nx;
				var totalSpace = Math.abs(_space) + x0;
				if(totalSpace > srcParentGeo.width){
					var cur0 = totalSpace-srcParentGeo.width-nx;   // 还要少一个间隙的空间
					x0 -= cur0;
				}
			}else{
				x0 = 10;
			}
	
			for (var i = 0; i < parallels.length; i++)
			{
				this.route(parallels[i], x0, y0);
				x0 -= nx;
				y0 += ny;
			}

			if(srcCell.parent.id != trgCell.parent.id){
				src.x = src.x - srcParentGeo.x;
				src.y = src.y - srcParentGeo.y;
				trg.x = trg.x - trgParentGeo.x;
				trg.y = trg.y - trgParentGeo.y;
			}
		}
	}
};
mxCustomEdgeLayout.prototype.route = function(edge, x, y)
{
	if (this.graph.isCellMovable(edge))
	{
		this.setEdgePoints(edge, [new mxPoint(x, y)]);
	}
};

路径:javascript\src\js\view\mxEdgeStyle.js

//  折线
	BlineConnector: function(state, source, target, points, result){
		var pt = (points!=null&&points.length>0)?points[0]:null;

		var vertical = false;
		var horizontal = false;

		if(source!=null && target!=null){
			if(pt!=null){
				var left = Math.min(source.x, target.x);
				var right = Math.max(source.x+source.width, target.x + target.width);

				var top = Math.min(source.y, target.y);
				var bottom = Math.max(source.y+source.height, target.y+target.height);

				pt = state.view.transformControlPoint(state, pt);

				vertical = pt.y < top || pt.y > bottom;
				horizontal = pt.x < left || pt.x > right;
			}else{
				var left = Math.max(source.x, target.x);
				var right = Math.min(source.x+source.width, target.x + target.width);

				vertical = left == right;

				if(!vertical){
					var top = Math.max(source.y, target.y);
					var bottom = Math.min(source.y+source.height, target.y+target.height);

					horizontal = top == bottom;
				}
			}

			if(!horizontal && (vertical || state.style[mxConstants.STYLE_ELBOW] == mxConstants.ELBOW_VERTICAL)){
				// 水平
				mxEdgeStyle.horizontalEdge(state, source, target, points, result);
			}else{
				// 垂直
				mxEdgeStyle.verticalEdge(state, source, target, points, result);
			}
		}
	},
	// 折线-水平
	horizontalEdge: function(state, source, target, points, result){},
	// 折线-垂直
	verticalEdge: function(state, source, target, points, result){
		var view = state.view;
		var model = view.graph.getModel();
		var src = view.getVisibleTerminal(state.cell, true);   // 源節點
		var trg = view.getVisibleTerminal(state.cell, false);  // 目標節點
		var scale = state.view.scale;

		var srcParent = model.getCell(src.parent.id);
		var srcParentGeo = model.getGeometry(srcParent);

		var trgParent = model.getCell(trg.parent.id);
		var trgParentGeo = model.getCell(trgParent);

		var srcg = model.getGeometry(src);
		var trgg = model.getGeometry(trg);

		var stateCell = model.getGeometry(state.cell);
		var stateCellClone = stateCell.clone();

		var srcGeo = srcg.clone();
		var trgGeo = trgg.clone();

		if(!window.cellMoved){
			if(srcGeo.x < trgGeo.x){
				if(points[0].x > (srcGeo.x + srcGeo.width)){
					if(srcGeo.right != null){
						srcGeo.right ++;
					}else{
						srcGeo.right = 1;
					}
					stateCellClone.right = srcGeo.right;
					stateCellClone.rightId = src.id;
				}

				if(points[0].x < trgGeo.x){
					if(trgGeo.left != null){
						trgGeo.left ++;
					}else{
						trgGeo.left = 1;
					}
					stateCellClone.left = trgGeo.left;
					stateCellClone.leftId = trg.id;
				}
			}else if(srcGeo.x > trgGeo.x){
				if(points[0].x - srcParentGeo.x < srcGeo.x){
					if(srcGeo.left != null){
						srcGeo.left ++;
					}else{
						srcGeo.left = 1;
					}
					stateCellClone.left = srcGeo.left;
					stateCellClone.leftId = src.id;
				}

				if(points[0].x - srcParentGeo.x > trgGeo.x+trgGeo.width){
					if(trgGeo.right != null){
						trgGeo.right ++;
					}else{
						trgGeo.right = 1;
					}
					stateCellClone.right = trgGeo.right;
					stateCellClone.rightId = trg.id;
				}
			}
			model.setGeometry(view.getVisibleTerminal(state.cell, true), srcGeo);
			model.setGeometry(view.getVisibleTerminal(state.cell, false), trgGeo);
			model.setGeometry(state.cell, stateCellClone);
		}else{
			if(srcGeo.x < trgGeo.x){
				var _resultRight = [];
				if(src.edges.length > 0){
					for(var i=0;i<src.edges.length;i++){
						var _e = src.edges[i];
						if(_e.geometry.rightId == src.id){
							_resultRight.push(_e.geometry.right);
						}
					}
				}
				var srcResult = getInsetEdgePosition(src.geometry.totalEdges, _resultRight, []);

				if(srcResult.length > 0){
					srcGeo.right = srcResult[0];
				}else{
					srcGeo.right = 1;
				}

				var _resultLeft = [];
				if(trg.edges.length > 0){
					for(var i=0;i<trg.edges.length;i++){
						var _e = trg.edges[i];
						if(_e.geometry.leftId == trg.id){
							_resultLeft.push(_e.geometry.left);
						}
					}
				}
				var trgResult = getInsetEdgePosition(trg.geometry.totalEdges, _resultLeft, []);

				if(trgResult.length > 0){
					trgGeo.left = trgResult[0];
				}else{
					trgGeo.left = 1;
				}

				stateCellClone.right = srcGeo.right;
				stateCellClone.left = trgGeo.left;
				stateCellClone.rightId = src.id;
				stateCellClone.leftId = trg.id;
			}else{
				var _resultLeft = [];
				if(src.edges.length > 0){
					for(var i=0;i<src.edges.length;i++){
						var _e = src.edges[i];
						if(_e.geometry.leftId == src.id){
							_resultLeft.push(_e.geometry.left);
						}
					}
				}
				var srcResult = getInsetEdgePosition(src.geometry.totalEdges, _resultLeft, []);
				if(srcResult.length > 0){
					srcGeo.left = srcResult[0];
				}else{
					srcGeo.left = 1;
				}

				var _resultRight = [];
				if(trg.edges.length > 0){
					for(var i=0;i<trg.edges.length;i++){
						var _e = trg.edges[i];
						if(_e.geometry.rightId == trg.id){
							_resultRight.push(_e.geometry.right);
						}
					}
				}
				var trgResult = getInsetEdgePosition(trg.geometry.totalEdges, _resultRight, []);
				if(trgResult.length > 0){
					trgGeo.right = trgResult[0];
				}else{
					trgGeo.right = 1;
				}
				stateCellClone.right = trgGeo.right;
				stateCellClone.left = srcGeo.left;
				stateCellClone.rightId = trg.id;
				stateCellClone.leftId = src.id;
			}
			model.setGeometry(view.getVisibleTerminal(state.cell, true), srcGeo);
			model.setGeometry(view.getVisibleTerminal(state.cell, false), trgGeo);
			model.setGeometry(state.cell, stateCellClone);
		}

		// 返回當前節點左邊或右邊空缺的位置
		function getInsetEdgePosition(total, arr, results){
			for(var i =0;i<total+2;i++){
				results.push(i+1);
			}
			if(arr.length > 0){
				for(var j=0;j<arr.length;j++){
					var index = results.indexOf(arr[j]);
					if(index > -1){
						results.splice(index, 1);
					}
				}
			}
			return results;
		}

		var pt = (points!=null&&points.length>0)?points[0] : null;
		var pts = state.absolutePoints;
		var p0 = pts[0];
		var pe = pts[pts.length - 1 ];

		if(pt!=null){
			pt = view.transformControlPoint(state, pt);
		}
		if(p0!=null){
			source = new mxCellState();
			source.x = p0.x;
			source.y = p0.y;
		}
		if(pe!=null){
			target = new mxCellState();
			target.x = pe.x;
			target.y = pe.y;
		}

		if(source != null && target!=null){
			var l = Math.max(source.x ,target.x);
			var r = Math.min(source.x+source.width, target.x+target.width);

			var x = (pt!=null)?pt.x : Math.round(r+(l-r)/2);

			var y1 = view.getRoutingCenterY(source);
			var y2 = view.getRoutingCenterY(target);

			if(pt!=null){
				if(pt.y>=source.y && pt.y <= source.y + source.height){
					y1 = pt.y;
				}
				if(pt.y>=target.y && pt.y <= target.y + target.height){
					y2 = pt.y;
				}
			}

			if(!mxUtils.contains(target, x, y1) && !mxUtils.contains(source, x, y1)){
				result.push(new mxPoint(x, y1));
			}

			if(!mxUtils.contains(target, x, y2) && !mxUtils.contains(source, x, y2)){
				result.push(new mxPoint(x, y2));
			}

			// 計算當前線坐標
			function setCoords(curLine, space, y, result){
				if(curLine % 2 == 0){
					result = y - Math.floor(space * (curLine / 2));
				}else{
					result = y + Math.floor(space * (Math.floor(curLine / 2)));
				}
				return result;
			}

			// 當線沒有拐點時(線為直線)
			if(result.length == 1){
				if(pt != null){
					if(!mxUtils.contains(target, x, pt.y) && !mxUtils.contains(source, x, pt.y)){
						result.push(new mxPoint(x, pt.y));
					}
				}else{
					var t = Math.max(source.y, target.y);
					var b = Math.min(source.y+source.height, target.y+target.height);

					result.push(new mxPoint(x, t+(b-t)/2));
				}
				if(!result[1]) return;
				result[0] = new mxPoint(0,0);
				result[0].x = result[1].x;
				if(source.y < target.y){
					result[0].y = source.y+source.height;
				}else{
					result[0].y = source.y;
				}

				result[2] = new mxPoint(0,0);
				result[2].x = result[1].x;
				if(source.y < target.y){
					result[2].y = target.y;
				}else{
					result[2].y = target.y+target.height;
				}
			}else{   // 折線
				var curStateCell = model.getGeometry(state.cell);
				var curSrcgeo = model.getGeometry(view.getVisibleTerminal(state.cell, true));
				var curTrggeo = model.getGeometry(view.getVisibleTerminal(state.cell, false));

				// 3段線,  4組坐標
				if(result.length > 1){
					if(result[1].x != result[2].x || result[1].y != result[2].y){
						// 第一個坐標點
						result[0] = new mxPoint(0,0);
						if(points[0].x < curSrcgeo.x && points[0].x < curTrggeo.x){
							var _x0 = source.x;
						}else if(points[0].x > curSrcgeo.x && points[0].x > curTrggeo.x){
							var _x0 = source.x+source.width;
						}else{
							if(points[0].x > curSrcgeo.x+curSrcgeo.width && points[0].x < curTrggeo.x){
								var _x0 = source.x + source.width;
							}else{
								var _x0 = source.x;
							}
						}
						result[0].x = _x0;
						var _y0 = view.getRoutingCenterY(source);
						if(source.x + source.width < target.x){
							var curLine = curSrcgeo.right;
						}else{
							var curLine = curSrcgeo.left;
						}
						var _space = curSrcgeo.space * scale;
						result[0].y = setCoords(curLine, _space, _y0, result[0].y);
						result[1].y = result[0].y;

						// 最後一個坐標點
						result[3] = new mxPoint(0,0);
						if(points[0].x < curSrcgeo.x && points[0].x < curTrggeo.x){
							var _x3 = target.x;
						}else if(points[0].x > curSrcgeo.x && points[0].x > curTrggeo.x){
							var _x3 = target.x+target.width;
						}else{
							if(points[0].x > curSrcgeo.x+curSrcgeo.width && points[0].x < curTrggeo.x){
								var _x3 = target.x;
							}else{
								var _x3 = target.x+target.width;
							}
						}

						result[3].x = _x3;
						var _y1 = view.getRoutingCenterY(target);
						if(source.x + source.width < target.x){
							var curLine = curTrggeo.left;
						}else{
							var curLine = curTrggeo.right;
						}
						var _space = curTrggeo.space * scale;
						result[3].y = setCoords(curLine, _space, _y1, result[3].y);
						result[2].y = result[3].y;
					}else{
						result[0] = new mxPoint(0,0);
						if(source.x < target.x){
							result[0].x = source.x + source.width;
						}else{
							result[0].x = source.x;
						}

						var _y0 = view.getRoutingCenterY(source);
						if(source.x+source.width < target.x){
							var curLine = curSrcgeo.right; 
						}else{
							var curLine = curSrcgeo.left; 
						}
						var _space = curSrcgeo.space * scale;
						result[0].y = setCoords(curLine, _space, _y0, result[0].y);
						result[1].y = result[0].y;

						var minSpace = Math.min(curSrcgeo.space, curTrggeo.space) * scale;
						result[1].x = setCoords(window.initNum, minSpace, result[1].x, result[1].x);
						result[2].x = result[1].x;

						result[3] = new mxPoint(0,0);
						if(source.x < target.x){
							result[3].x = target.x;
						}else{
							result[3].x = target.x + target.width;
						}

						var _y1 = view.getRoutingCenterY(target);
						if(source.x + source.width < target.x){
							var curLine = curTrggeo.left;
						}else{
							var curLine = curTrggeo.right;
						}
						var _space = curTrggeo.space * scale;
						result[3].y = setCoords(curLine, _space, _y1, result[3].y);
						result[2].y = result[3].y;

						window.initNum ++; // 兩節點之間x軸一樣,每畫一次則加1
					}
				}else{  // 2段線,  3組坐標
					if(source.x < target.x){
						if(result[1].y > source.y && result[1].y < source.y+source.height){
							if(source.y < target.y){
								var curLine = curStateCell.right;
							}else{
								var curLine = curStateCell.left;
							}
							var _space = curSrcgeo.space*scale;
							result[0] = new mxPoint(0,0);
							var _x0 = source.x < target.x ? source.x+source.width : source.x;
							result[0].x = _x0;
							result[1].y = setCoords(curLine, _space, result[1].y, result[1].y);
							result[0].y = result[1].y;

							result[2] = new mxPoint(0,0);
							result[2].x = result[1].x;
							if(source.y < target.y){
								result[2].y = target.y;
							}else{
								result[2].y = target.y+target.height;
							}
						}else {
							if(source.x < target.x && source.y+srcParentGeo.y < source.y+srcParentGeo.y+source.height){
								if(source.x < target.x){
									var curLine = curStateCell.left;
								}else{
									var curLine = curStateCell.right;
								}

								var _space = curTrggeo.space * scale;
								result[0] = new mxPoint(0,0);
								result[0].x = result[1].x;
								if(source.y < target.y){
									result[0].y = source.y + source.height;
								}else{
									result[0].y = source.y;
								}

								result[2] = new mxPoint(0,0);
								result[2].x = source.x < target.x ? target.x : target.x+target.width;
								result[1].y = setCoords(curLine, _space, result[1].y, result[1].y);
								result[2].y = result[1].y;
							}
						}
					}else{
						if(result[1].y > source.y && result[1].y < source.y + source.height){
							if(source.x < target.x){
								var curLine = curStateCell.right;
							}else{
								var curLine = curStateCell.left;
							}
							var _space = curSrcgeo.space * scale;
							result[0] = new mxPoint(0,0);
							var _x0 = source.x < target.x ? source.x+source.width : source.x;
							result[0].x = _x0;
							result[1].y = setCoords(curLine, _space, result[1].y, result[1].y);
							result[0].y = result[1].y;

							result[2] = new mxPoint(0,0);
							result[2].x = result[1].x;
							if(source.y < target.y){
								result[2].y = target.y;
							}else{
								result[2].y = target.y+target.height;
							}
						}else{
							if(source.x > target.x){
								var curLine = curStateCell.right;
							}else{
								var curLine = curStateCell.left;
							}

							var _space = curTrggeo.space * scale;
							result[0] = new mxPoint(0,0);
							result[0].x = result[1].x;
							if(source.y < target.y){
								result[0].y = source.y+source.height;
							}else{
								result[0].y = source.y;
							}

							result[2] = new mxPoint(0,0);
							result[2].x = source.x < target.x ? target.x : target.x+target.width;
							result[1].y = setCoords(curLine, _space, result[1].y, result[1].y);
							result[2].y = result[1].y;
						}
					}
				}
			}
		}
	},
	// 直线
	straightLineConnector: function(state, source, target, points, result) {
		result = result ? result : [];
		var view = state.view;
		var model = view.graph.getModel();
		var angle = Math.atan2((source.y-target.y), (source.x-target.x));
		var theta = parseInt(angle*(180/Math.PI));
		var spgeo = model.getGeometry(model.getCell(view.getVisibleTerminal(state.cell, true).parent.id));
		var tpgeo = model.getGeometry(model.getCell(view.getVisibleTerminal(state.cell, false).parent.id));
		var src = view.getVisibleTerminal(state.cell, true);
		var srcgeo = model.getGeometry(src);
		var srcgeoclone = srcgeo.clone();
		var trg = view.getVisibleTerminal(state.cell, false);
		var trggeo = model.getGeometry(trg);
		var trggeoclone = trggeo.clone();
		var stateCell = model.getGeometry(state.cell);
		var sourceCX = source.getCenterX();
		var sourceCY = source.getCenterY();
		var stateCellClone = stateCell.clone();

		var obj = {};
		obj.sid = source.cell.id;
		obj.tid = target.cell.id;
		obj.sX = source.x;
		obj.sY = source.y;
		obj.sWidth = source.width;
		obj.sHeight = source.height;
		obj.spY = spgeo.y;
		obj.tX = target.x;
		obj.tY = target.y;
		obj.tWidth = target.width;
		obj.tHeight = target.height;
		obj.tpY = tpgeo.y;
		var trgSpace = model.getGeometry(view.getVisibleTerminal(state.cell, false)).space;
		var start = 0;
		obj.trgSpace = trgSpace;
		var x2 = null;
		var y2 = null;

		function intervalSpace(sourceLength, index, space){
			var resultNum = 0;
			if(index){
				if(index %2 ==0){
					resultNum = intervalSpace(sourceLength, index-1, space) + space * index;
				}else{
					resultNum = intervalSpace(sourceLength, index-1, space) - space * index;
				}
			}else{
				resultNum = sourceLength/2;
			}
			return resultNum;
		}

		function calculateCoords(){
			var heightNum = intervalSpace(obj.tHeight, start, obj.trgSpace);
			var widthNum = intervalSpace(obj.tWidth, start, obj.trgSpace);

			x2 = obj.tX + Math.floor(widthNum);
			y2 = obj.tY + Math.floor(heightNum);
			if(theta < -90 || theta > 0 && theta < 90){
				x2 = obj.tX + obj.tWidth - widthNum;
			}

			var leftLine = mxUtils.intersection(sourceCX, sourceCY, x2, y2, obj.tX, obj.tY, obj.tX, obj.tY+obj.tHeight);
			var topLine = mxUtils.intersection(sourceCX, sourceCY, x2, y2, obj.tX, obj.tY, obj.tX+obj.tWidth, obj.tY);
			var rightLine = mxUtils.intersection(sourceCX, sourceCY, x2, y2, obj.tX+obj.tWidth, obj.tY, obj.tX+obj.tWidth, obj.tY+obj.tHeight);
			var bottomLine = mxUtils.intersection(sourceCX, sourceCY, x2, y2, obj.tX, obj.tY+obj.tHeight, obj.tX+obj.tWidth, obj.tY+obj.tHeight);
			
			return leftLine || topLine || rightLine || bottomLine;
		}

		var intersection = calculateCoords();

		function compareCoords (){
			for (var i=0;i<trg.edges.length;i++){
				var stateCellGeo = model.getGeometry(trg.edges[i]);
				if(stateCellGeo.intersection){
					if(intersection &&
						((Math.ceil(intersection.x) == stateCellGeo.intersection.x && Math.ceil(intersection.y) == stateCellGeo.intersection.y) ||
						((Math.floor(intersection.x) > stateCellGeo.intersection.x -1 && Math.floor(intersection.x) < stateCellGeo.intersection.x +1 ) && 
						(Math.floor(intersection.y) > stateCellGeo.intersection.y-1 && Math.floor(intersection.y) < stateCellGeo.intersection.y+1)))
					){
						start ++;
						intersection = calculateCoords();
						compareCoords();
					}
				}
				if(view.getVisibleTerminal(trg.edges[i], false) == src){
					if(stateCellGeo.fintersection){
						if(intersection &&
							((Math.ceil(intersection.x) == stateCellGeo.fintersection.x && Math.ceil(intersection.y) == stateCellGeo.fintersection.y) ||
							((Math.floor(intersection.x) > stateCellGeo.fintersection.x -1 && Math.floor(intersection.x) < stateCellGeo.fintersection.x +1 ) && 
							(Math.floor(intersection.y) > stateCellGeo.fintersection.y-1 && Math.floor(intersection.y) < stateCellGeo.fintersection.y+1)))
						){
							start ++;
							intersection = calculateCoords();
							compareCoords();
						}
					}
				}
			}
		}

		compareCoords();

		function getFromCoords(){
			var fLeftLine = mxUtils.intersection( x2, y2, sourceCX, sourceCY, obj.sX, obj.sY, obj.sX, obj.sY+obj.sHeight);
			var ftopLine = mxUtils.intersection(x2, y2, sourceCX, sourceCY, obj.sX, obj.sY, obj.sX+obj.sWidth, obj.sY);
			var frightLine = mxUtils.intersection(x2, y2, sourceCX, sourceCY, obj.sX+obj.sWidth, obj.sY, obj.sX+obj.sWidth, obj.sY+obj.sHeight);
			var fbottomLine = mxUtils.intersection(x2, y2, sourceCX, sourceCY, obj.sX, obj.sY+obj.sHeight, obj.sX+obj.sWidth, obj.sY+obj.sHeight);
			
			return fLeftLine || ftopLine || frightLine || fbottomLine;
		}

		if(intersection){
			var resultCoords = new mxPoint(Math.ceil(intersection.x), Math.ceil(intersection.y));
			result.push(resultCoords);
			stateCellClone.intersection = resultCoords;
			stateCellClone.fintersection = getFromCoords();
			model.setGeometry(state.cell, stateCellClone);
		}

		return result;
	},

路径:javascript\src\js\view\mxGraph.js

// 添加线是否可移动初始化参数
mxGraph.prototype.isEdgeSelected = true;

// 设置线是否可移动
mxGraph.prototype.isSelectedEdge = function(val){
	this.isEdgeSelected = val;
}

 // 修改此方法,设置线及父节点不可选中且不可移动
mxGraph.prototype.setSelectionCell = function(cell)
{
	// this.getSelectionModel().setCell(cell);
	var model = this.view.graph.getModel();
	var edgeIsSelected = cell.getAttribute('isSelected');
	if((!this.isEdgeSelected && model.isEdge(cell)) || edgeIsSelected == 'false'){
		this.clearSelection();  //  清除已选中的节点
		this.removeSelectionCell(cell); // 不允许选中当前节点
		this.cellsLocked = true;   // 上锁
	}else{
		this.getSelectionModel().setCell(cell);
		this.cellsLocked = false;
	}
};

// 修改此方法
mxGraphView.prototype.getPoint = function(state, geometry)
{
	var that = this;
	var x = state.getCenterX();
	var y = state.getCenterY();
	var srcId = state.cell.source.id;
	var trgId = state.cell.target.id;
	var id = srcId+'+'+trgId;
	var reversId = trgId+'+'+srcId;
	var p0y = null;
	var pey = null;
	var p0x = null;
	var pex = null;
	var maxPY = null;
	var minPY = null;
	var maxPX = null;
	var minPX = null;

	// 直线需要重新判断当前id,把双向变成单向
	if(that.graph.lineType == 'straightLine'){
		if(window.edgesLabelCountMap && window.edgesLabelCountMap[id] != null){
			id = id;
		}
		if(window.edgesLabelCountMap && window.edgesLabelCountMap[reversId] != null){
			id = reversId;
		}
	}
	// 折线
	if(that.graph.lineType == 'brokenLine'){
		if(window.edgesLabelMap && window.edgesLabelMap[id] != null){
			id = id;
		}
		if(window.edgesLabelMap && window.edgesLabelMap[reversId] != null){
			id = reversId;
		}
	}
	// 判断是否为空对象
	function isEmptyObject(obj){
		for(var val in obj){
			return false;
		}
		return true;
	}
	// 折线
	if(that.graph.lineType == 'brokenLine'){
		if(!window.edgesLabelMap){
			window.edgesLabelMap = {};
			window.edgesLabelMap[id] = {
				counted: 1
			}
		}else{
			if(window.edgesLabelMap[id] != null){
				window.edgesLabelMap[id].counted ++;
			}else{
				window.edgesLabelMap[id] = {
					counted: 1
				}
			}
		}
	}
	// 直线
	if(that.graph.lineType == 'straightLine'){
		if(!window.edgesLabelCountMap){
			window.edgesLabelCountMap = {};
			window.edgesLabelCountMap[id] = {
				counted : 0
			}
		}else{
			if(window.edgesLabelCountMap[id] != null){
				window.edgesLabelCountMap[id],counted ++;
			}else{
				window.edgesLabelCountMap[id] = {
					counted : 0
				}
			}
		}
	}

	
	if (state.segments != null && (geometry == null || geometry.relative))
	{
		var gx = (geometry != null) ? geometry.x / 2 : 0;
		var pointCount = state.absolutePoints.length;
		var dist = Math.round((gx + 0.5) * state.length);
		var segment = state.segments[0];
		var length = 0;				
		var index = 1;

		while (dist >= Math.round(length + segment) && index < pointCount - 1)
		{
			length += segment;
			segment = state.segments[index++];
		}

		var factor = (segment == 0) ? 0 : (dist - length) / segment;
		var p0 = state.absolutePoints[index-1];
		var pe = state.absolutePoints[index];

		if (p0 != null && pe != null)
		{
			var gy = 0;
			var offsetX = 0;
			var offsetY = 0;
			p0y = p0.y;
			pey = pe.y;
			p0x = p0.x;
			pex = pe.x;
			maxPY = Math.max(p0y, pey);
			minPY = Math.min(p0y, pey);
			maxPX = Math.max(p0x, pex);
			minPX = Math.min(p0x, pex);

			if (geometry != null)
			{
				gy = geometry.y;
				var offset = geometry.offset;
				
				if (offset != null)
				{
					offsetX = offset.x;
					offsetY = offset.y;
				}
			}

			var dx = pe.x - p0.x;
			var dy = pe.y - p0.y;
			var nx = (segment == 0) ? 0 : dy / segment;
			var ny = (segment == 0) ? 0 : dx / segment;
			
			x = p0.x + dx * factor + (nx * gy + offsetX) * this.scale;
			y = p0.y + dy * factor - (ny * gy - offsetY) * this.scale;
		}
		if(that.graph.lineType=='brokenLine'){
			if(!isEmptyObject(window.edgesLabelMap)){
				function compareEdgeLabelPositionBL(){
					if(window.edgesLabelMap[id].counted %2 == 0){
						y = p0.y + (pe.y-p0.y) / 2 - 5*window.edgesLabelMap[id].counted;
					}else{
						y = p0.y + (pe.y-p0.y) / 2 + 5*window.edgesLabelMap[id].counted;
					}
					if(maxPY != null && minPY != null){
						if(y<minPY || y>maxPY){
							window.edgesLabelMap[id].counted = 1;
							compareEdgeLabelPositionBL();
						}
					}
				}
				if(p0.x == pe.x && Math.abs(pe.y-p0.y) > 20){
					compareEdgeLabelPositionBL();
				}
			}
		}
		if(that.graph.lineType=='straightLine'){
			function compareEdgeLabelPositionSL(){
				if(window.edgesLabelCountMap[id].counted % 2 == 0){
					factor = (dist-10*window.edgesLabelCountMap[id].counted) / segment;
				}else{
					factor = (dist+10*window.edgesLabelCountMap[id].counted) / segment;
				}
				x = p0.x + dx * factor.toFixed(2) + (nx*gy+offsetX) * that.scale;
				y = p0.y + dy * factor.toFixed(2) + (ny*gy+offsetY) * that.scale;

				if(maxPY != null && minPY!=null && maxPX != null && minPX != null){
					// 当最后坐标x大于当前线最大的x坐标||当最后坐标x小于当前线最小的x坐标||
					// 当最后坐标y大于当前线最大的y坐标||当最后坐标y小于当前线最小的y坐标
					if(y<minPY||y>maxPY || x<minPX || x > maxPX){
						window.edgesLabelCountMap[id].counted = 0;
						compareEdgeLabelPositionSL();
					}
				}
			}
			compareEdgeLabelPositionSL();
		}
	}
	else if (geometry != null)
	{
		var offset = geometry.offset;
		
		if (offset != null)
		{
			x += offset.x;
			y += offset.y;
		}
	}
	
	return new mxPoint(x, y);		
};
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值