2017-01-09 220 views
0

我正在使用具有500多个节点的d3树(第二级中有一个根节点和500/1000个子节点)。箭头看起来完美,多达50个子节点,但在左侧和右侧节点上看起来更多,节点和路径顶部显示的箭头对角地与节点边缘相交。 如何解决这个问题,箭头应该触摸节点的路径相交节点?使用的节点是矩形,如在这个问题中给出的Arrows are not touching to nodes in d3.js箭头不触及d3.js树节点中的节点

+0

从如何寻求帮助 - '求调试帮助(“为什么不是这个代码的工作?”)问题必须包括所期望的行为,一个特定的问题或错误,并在问题本身重现它所需的最短的代码 – Mark

+0

https://jsfiddle.net/oo66o0q0/我创建此jfiddle.Issue可重现那里 – user6821214

+0

http://jsfiddle.net/oo66o0q0/ 2/ – user6821214

回答

1

好吧,这里是你的解决方案。这就是我所说的“后退”方法。这与我在this question中使用的方法相同。它通过拟合路径,然后减去你的方形加上标记头的“半径”来工作。

夫妇的事情第一,你只需要追加“标记”def一次,它可以用于所有的行。其次,我将路径切换为自上而下,让他们绘制我将所有的东西 - 从孩子到父母。这需要额外旋转头部。

下面的代码:

var width = 500; 
 
var height = 500; 
 
var nodeWidth = 40; 
 
var nodeHeight = 40; 
 
var circleRadius = 5; 
 
var diagramLayout; 
 
var graphData = { 
 
    "nodes": [{ 
 
    "uid": "Term20", 
 
    "name": "Term20", 
 
    "image": "images/Term.png" 
 
    }, { 
 
    "uid": "glossforArrow", 
 
    "name": "glossforArrow", 
 
    "image": "images/Glossary.png" 
 
    }, { 
 
    "uid": "Term43", 
 
    "name": "Term43", 
 
    "image": "images/Term.png" 
 
    }, { 
 
    "uid": "Term1", 
 
    "name": "Term43", 
 
    "image": "images/Term.png" 
 
    }, { 
 
    "uid": "Term2", 
 
    "name": "Term43", 
 
    "image": "images/Term.png" 
 
    }], 
 
    "links": [{ 
 
    "source": "glossforArrow", 
 
    "target": "Term20", 
 
    "direction": "output", 
 
    "label": "Owned Terms" 
 
    }, { 
 
    "source": "glossforArrow", 
 
    "target": "Term43", 
 
    "direction": "output", 
 
    "label": "Owned Terms" 
 
    }, { 
 
    "source": "glossforArrow", 
 
    "target": "Term1", 
 
    "direction": "output", 
 
    "label": "Owned Terms" 
 
    }, { 
 
    "source": "glossforArrow", 
 
    "target": "Term3", 
 
    "direction": "output", 
 
    "label": "Owned Terms" 
 
    }, { 
 
    "source": "glossforArrow", 
 
    "target": "Term4", 
 
    "direction": "output", 
 
    "label": "Owned Terms" 
 
    }, { 
 
    "source": "glossforArrow", 
 
    "target": "Term5", 
 
    "direction": "output", 
 
    "label": "Owned Terms" 
 
    }, { 
 
    "source": "glossforArrow", 
 
    "target": "Term6", 
 
    "direction": "output", 
 
    "label": "Owned Terms" 
 
    }, { 
 
    "source": "glossforArrow", 
 
    "target": "Term7", 
 
    "direction": "output", 
 
    "label": "Owned Terms" 
 
    }, { 
 
    "source": "glossforArrow", 
 
    "target": "Term8", 
 
    "direction": "output", 
 
    "label": "Owned Terms" 
 
    }, { 
 
    "source": "glossforArrow", 
 
    "target": "Term9", 
 
    "direction": "output", 
 
    "label": "Owned Terms" 
 
    }, { 
 
    "source": "glossforArrow", 
 
    "target": "Term2", 
 
    "direction": "output", 
 
    "label": "Owned Terms" 
 
    }] 
 
}; 
 

 
treeInitialize(graphData) 
 

 

 
function treeInitialize(graphData) { 
 

 
    diagramLayout = d3.select("#diagramLayout") 
 
    .attr("id", "diagramLayout") //set id 
 
    .attr("width", width) //set width 
 
    .attr("height", height) //set height 
 
    .append("g") 
 
    .attr("transform", "translate(" + 20 + "," + 20 + ")") 
 

 
    markerRefx = 40; 
 

 
    var data2 = graphData.links.filter(function(l) { 
 
    if (l.target == undefined && l.source == undefined) { 
 
     return false; 
 
    } else { 
 
     return true; 
 
    } 
 
    }); 
 
    data2.push(JSON.parse('{"target":"glossforArrow","source":""}')) 
 

 
    var treeData = d3.stratify().id(function(d) { 
 
    return d.target; 
 
    }).parentId(function(d) { 
 
    return d.source; 
 
    })(data2) 
 

 
    nodes = d3.hierarchy(treeData, function(d) { 
 
    return d.children; 
 
    }); 
 

 
    var levelWidth = [1]; 
 
    var childCount = function(level, n) { 
 

 
    if (n.children && n.children.length > 0) { 
 
     if (levelWidth.length <= level + 1) levelWidth.push(0); 
 

 
     levelWidth[level + 1] += n.children.length; 
 
     n.children.forEach(function(d) { 
 
     childCount(level + 1, d); 
 
     }); 
 
    } 
 
    }; 
 
    childCount(0, nodes); 
 
    newHeight = d3.max(levelWidth) * 100; 
 
    var tree = d3.tree().size([height, width]) 
 

 
    tree.size([newHeight, height/2]); 
 

 
    tree.separation(function(a, b) { 
 
    return a.parent == b.parent ? 50 : 100; 
 
    }); 
 
    nodes = tree(nodes); 
 
    treeLayout(nodes); 
 

 
    function treeLayout(nodes) { 
 

 
    var node = diagramLayout.selectAll(".node"); 
 
    node = node.data(nodes.descendants()); 
 

 
    var link = diagramLayout.selectAll(".link") 
 
     .data(nodes.descendants().slice(1)) 
 
     .enter().append("path") 
 
     .attr("class", "link") 
 
     .attr("fill", "none") 
 
     .attr("stroke", "#000") 
 
     .attr("stroke-width", "1px") 
 
     .attr("stroke-opacity", "0.3") 
 
     .attr("d", function(d) { 
 
     return connector(d.parent, d); 
 
     }) 
 

 
    //nodes.descendants().slice(1).forEach(function(d) { 
 

 
    var mark = diagramLayout.append("svg:defs").selectAll("marker") // 
 
     .data(["start"]) // Different link/path types can be defined here 
 
     .enter().append("svg:marker") // This section adds in the arrows 
 
     .attr("id", String) 
 
     .attr("viewBox", "0 -5 10 10") 
 
     .attr("refX", 0) 
 
     .attr("refY", 0) 
 
     .attr("markerWidth", 5) 
 
     .attr("markerHeight", 5) 
 
     .attr("orient", "auto") 
 
     .attr("stroke", "#000") 
 
     .attr("fill", "#000") 
 
     .append("svg:path") 
 
     .attr("d", "M0,-5L10,0L0,5") 
 
     .style("stroke-width", "0.3px") 
 
     //.attr("transform","rotate(180,5, 0)"); 
 

 
    // \t }); \t 
 

 
    link.attr("marker-end", "url(#start)") 
 
     .each(function(d, i, j) { 
 

 
     var self = d3.select(this), 
 
      t = this.getTotalLength(), 
 
      p = this.getPointAtLength(t - 25); 
 

 
     self.attr("d", connector(d.parent, p)); 
 
     }) 
 

 

 

 
    var nodeEnter = node.enter().append("g") 
 
     .attr("class", "node") 
 
     .attr("height", nodeHeight) 
 
     .attr("width", nodeWidth) 
 
    nodeEnter.attr("transform", function(d) { 
 
     return "translate(" + project(d.x, d.y) + ")"; 
 
    }) 
 

 

 
    var nodeIcon = nodeEnter.append("rect") 
 
     .attr("class", "rect") 
 
     .attr("x", -20) 
 
     .attr("y", -20) 
 
     .attr("rx", 10) 
 
     .attr("width", 40) 
 
     .attr("height", 40) 
 
     .attr("stroke-width", function(d) { 
 
     return Math.sqrt(2); 
 
     }) 
 
     .attr("stroke-opacity", "0.3") 
 
     .attr("stroke", "#000") 
 
     .attr("fill", "none") 
 

 

 
    //wrap(nodeText, 8) \t 
 
    } 
 

 
} 
 

 
function connector(from, to) { 
 
    return "M" + project(from.x, from.y) + "C" + project(from.x, (from.y + to.y)/2) + " " + project(to.x, (from.y + to.y)/2) + " " + project(to.x, to.y); 
 
} 
 

 
function project(x, y) { 
 

 
    return [x, y]; 
 
}
.node { 
 
    stroke: #fff; 
 
    stroke-width: 1.5px; 
 
} 
 
.link { 
 
    stroke: #000; 
 
    stroke-opacity: .6; 
 
}
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<div id="mainScreen" style="height:100%;width:100%;position:absolute;"> 
 
    <svg id="diagramLayout" style="height:100%;width:100%;position:absolute;"> 
 
    </svg> 
 

 
</div>