I am using d3 tree with more than 500 nodes(one root and 500/1000 child nodes to it in 2nd level). Arrows looks perfect up-to 50 child nodes but more than that on left and right side nodes, arrows shown at top of node and path are intersects node edge diagonally. how to resolve this issue in such way that arrow should touch node where path intersect node?Nodes used are rectangular as given in this question Arrows are not touching to nodes in d3.js
Asked
Active
Viewed 797 times
0
-
From the how to ask for help - `Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself` – Mark Jan 11 '17 at 14:30
-
https://jsfiddle.net/oo66o0q0/ I created this jfiddle.Issue is reproducible there – user6821214 Jan 12 '17 at 05:41
-
http://jsfiddle.net/oo66o0q0/2/ – user6821214 Jan 12 '17 at 05:51
-
Is there any solution on this issue? – user6821214 Jan 17 '17 at 04:57
1 Answers
2
All right, all right here's your solution. This is what I call the "back-off" approach. It's the same approach I used in this question. It works by fitting the path and then subtracting off of it the "radius" of your square plus marker head.
Couple things first, you only need to append the "marker" def once, it can be used on all the lines. Second, I switched the paths to draw top down, you had them drawing what I would all backwards - from child to parent. This requires additional rotation of the head.
Here's the code:
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)");
// });
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)
}
}
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>