Skip to content

Instantly share code, notes, and snippets.

@Jverma
Last active August 29, 2015 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jverma/1f8f533eac7c3a3cd2e5 to your computer and use it in GitHub Desktop.
Save Jverma/1f8f533eac7c3a3cd2e5 to your computer and use it in GitHub Desktop.
Hive Plot with mouseover

Attempt at understanding Hive Plot and creating a D3 visual. Mouseover at each node shows the name and type of the node.

"Hive plots define a linear layout for nodes, grouping nodes by type and arranging them along radial axes based on some property of data. The explicit position encoding has the potential to better reveal the network structure while communicating additional information." - Mike Bostock's blog on Hive Plots.

d3.hive={},d3.hive.link=function(){function t(t,s){var u,h=a(r,this,t,s),i=a(n,this,t,s);h.a>i.a&&(u=i,i=h,h=u),i.a-h.a>Math.PI&&(h.a+=2*Math.PI);var e=h.a+(i.a-h.a)/3,c=i.a-(i.a-h.a)/3;return h.r0-h.r1||i.r0-i.r1?"M"+Math.cos(h.a)*h.r0+","+Math.sin(h.a)*h.r0+"L"+Math.cos(h.a)*h.r1+","+Math.sin(h.a)*h.r1+"C"+Math.cos(e)*h.r1+","+Math.sin(e)*h.r1+" "+Math.cos(c)*i.r1+","+Math.sin(c)*i.r1+" "+Math.cos(i.a)*i.r1+","+Math.sin(i.a)*i.r1+"L"+Math.cos(i.a)*i.r0+","+Math.sin(i.a)*i.r0+"C"+Math.cos(c)*i.r0+","+Math.sin(c)*i.r0+" "+Math.cos(e)*h.r0+","+Math.sin(e)*h.r0+" "+Math.cos(h.a)*h.r0+","+Math.sin(h.a)*h.r0:"M"+Math.cos(h.a)*h.r0+","+Math.sin(h.a)*h.r0+"C"+Math.cos(e)*h.r1+","+Math.sin(e)*h.r1+" "+Math.cos(c)*i.r1+","+Math.sin(c)*i.r1+" "+Math.cos(i.a)*i.r1+","+Math.sin(i.a)*i.r1}function a(t,a,r,n){var e=t.call(a,r,n),c=+("function"==typeof s?s.call(a,e,n):s)+i,o=+("function"==typeof u?u.call(a,e,n):u),M=u===h?o:+("function"==typeof h?h.call(a,e,n):h);return{r0:o,r1:M,a:c}}var r=function(t){return t.source},n=function(t){return t.target},s=function(t){return t.angle},u=function(t){return t.radius},h=u,i=-Math.PI/2;return t.source=function(a){return arguments.length?(r=a,t):r},t.target=function(a){return arguments.length?(n=a,t):n},t.angle=function(a){return arguments.length?(s=a,t):s},t.radius=function(a){return arguments.length?(u=h=a,t):u},t.startRadius=function(a){return arguments.length?(u=a,t):u},t.endRadius=function(a){return arguments.length?(h=a,t):h},t};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hive Link Plot</title>
<style type="text/css">
.link{
fill: none;
stroke-width: 1.5px;
}
.axis, .node{
stroke: #000;
stroke-width: 1.5px;
}
.tooltip{
position: absolute;
width: 50px;
height: 30px;
padding: 2px;
font: 12px sans-serif;
background: lightgreen;
border: 0px;
pointer-events: none;
}
/*.link:hover{
stroke: red;
stroke-opacity:.9;
}*/
</style>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="d3.hive.min.js"></script>
<script type="text/javascript">
var width = 960;
var height = 500;
var outerRadius = 240;
var innerRadius = 40;
var angle = d3.scale.ordinal()
.domain(d3.range(4))
.rangePoints([0,2 * Math.PI]);
var radius = d3.scale.linear()
.range([innerRadius, outerRadius]);
var color = d3.scale.category10()
.domain(d3.range(20));
var nodes = [
{x: 0, y: .1, name:"A"},
{x: 0, y: .9, name:"B"},
{x: 1, y: .2, name:"C"},
{x: 1, y: .3, name: "D"},
{x: 2, y: .1, name: "E"},
{x: 2, y: .8, name: "F"},
{x: 1, y: .4, name: "G"},
{x: 2, y:.2, name: "H"},
{x: 2, y: .7, name: "I"},
{x: 2, y: .4, name: "J"},
{x: 1, y: .6, name: "K"}
];
var links = [
{source: nodes[0], target: nodes[2]},
{source: nodes[1], target: nodes[3]},
{source: nodes[2], target: nodes[4]},
{source: nodes[2], target: nodes[5]},
{source: nodes[3], target: nodes[5]},
{source: nodes[4], target: nodes[0]},
{source: nodes[5], target: nodes[1]},
{source: nodes[1], target: nodes[4]},
{source: nodes[1], target: nodes[6]},
{source: nodes[6], target: nodes[3]},
{source: nodes[4], target: nodes[7]},
{source: nodes[4], target: nodes[7]},
{source: nodes[7], target: nodes[5]},
{source: nodes[7], target: nodes[2]},
{source: nodes[9], target: nodes[2]},
{source: nodes[8], target: nodes[6]},
{source: nodes[3], target: nodes[9]},
{source: nodes[1], target: nodes[8]},
{source: nodes[4], target: nodes[10]},
{source: nodes[10], target: nodes[3]},
{source: nodes[4], target: nodes[10]},
{source: nodes[8], target: nodes[7]},
{source: nodes[4], target: nodes[9]},
{source: nodes[1], target: nodes[7]},
{source: nodes[10], target: nodes[7]},
];
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width/2 + "," + height/2 + ")");
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
svg.selectAll(".axis")
.data(d3.range(3))
.enter().append("line")
.attr("class", "axis")
.attr("transform", function(d){ return "rotate(" + degrees(angle(d)) + ")";})
.attr("x1", radius.range()[0])
.attr("x2", radius.range()[1]);
svg.selectAll(".link")
.data(links)
.enter().append("path")
.attr("class", "link")
.attr("d", d3.hive.link()
.angle(function(d) { return angle(d.x); })
.radius(function(d) { return radius(d.y); }))
.style("stroke", function(d) { return color(d.source.x); });
svg.selectAll(".node")
.data(nodes)
.enter().append("circle")
.attr("class", "node")
.attr("transform", function(d) { return "rotate(" + degrees(angle(d.x)) + ")"; })
.attr("cx", function(d) { return radius(d.y); })
.attr("r", 5)
.style("fill", function(d) { return color(d.x); })
.on("mouseover", function(d){
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html("Node - " + d.name + "<br/>" + "Type - " + d.x)
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d){
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
function degrees(radians) {
return radians / Math.PI * 180 - 90;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment