This is an alternative to: Mobile Patent Suits
The mobile patent suits version is here
How? The width of the links and the length & width of arrow-heads are determined by parameters. These parameters are read from the link properties. Nodes must have a property named "r" which then determines the radius of representing circles. This property is used by the creation of the polygon to shorten the link preventing the arrow head disappearing behind the target node.
Explanation of the Code: Click here to see the picture
Why? svg markers don't seem to be easy to play with, particularly if node radii vary.
What more can be done? One may create curved links by using svg path instead of polygon.
xxxxxxxxxx
<meta charset="utf-8">
<style>
.link {
stroke: white;
fill: black;
}
.node {
fill: steelblue;
stroke: #fff;
stroke-width: 2px;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var width = 960,
height = 500,
nodes = [{r: 10}, {r: 15}, {r: 20}, {r: 25}],
list = [[0, 1], [0, 2], [1, 2], [2, 1], [2, 0], [2, 3], [3, 1], [0, 3]],
links = list.map(createLinks);
function createLinks (a) {
return {source: a[0], target: a[1], linkWidth: 5, headLength:20, headWidth: 8}
}
var force = d3.layout.force()
.size([width, height])
.nodes(nodes)
.links(links)
.linkDistance(150)
.on("tick", tick)
.start();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svgLinks = svg.selectAll(".link").data(links)
.enter().append("polygon")
.attr("class", "link");
svgNodes = svg.selectAll(".node").data(nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", function (d) {return d.r})
.call(force.drag);
function tick() {
svgNodes
.attr("cx", function (d) {return d.x})
.attr("cy", function (d) {return d.y});
svgLinks
.attr("points", calculatePolygon);
}
function calculatePolygon(d) {
var p2 = d.source,
w = diff(d.target, p2),
wl = length(w),
v1 = scale(w, (wl - d.target.r) / wl),
p1 = sum(p2, v1),
v2 = scale(rotate90(w), d.linkWidth / length(w)),
p3 = sum(p2, v2),
v1l = length(v1),
v3 = scale(v1, (v1l - d.headLength) / v1l),
p4 = sum(p3, v3),
v2l = length(v2),
v4 = scale(v2, d.headWidth / v2l),
p5 = sum(p4, v4);
return pr(p1) +" "+ pr(p2) +" "+ pr(p3) +" "+ pr(p4) +" "+ pr(p5);
function length(v) {return Math.sqrt(v.x * v.x + v.y * v.y)}
function diff(v, w) {return {x: v.x - w.x, y: v.y - w.y}}
function sum(v, w) {return {x: v.x + w.x, y: v.y + w.y}}
function scale(v, f) {return {x: f * v.x, y: f * v.y}}
function rotate90(v) {return {x: v.y, y: -v.x}} // clockwise
function pr(v) {return v.x +","+ v.y}
}
</script>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js