See my article on Krzywinski’s Hive Plots. See also area 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> | |
| <meta charset="utf-8"> | |
| <style> | |
| .link { | |
| fill: none; | |
| stroke-width: 1.5px; | |
| } | |
| .axis, .node { | |
| stroke: #000; | |
| stroke-width: 1.5px; | |
| } | |
| </style> | |
| <body> | |
| <script src="//d3js.org/d3.v3.min.js"></script> | |
| <script src="d3.hive.min.js"></script> | |
| <script> | |
| var width = 960, | |
| height = 500, | |
| innerRadius = 40, | |
| outerRadius = 240; | |
| var angle = d3.scale.ordinal().domain(d3.range(4)).rangePoints([0, 2 * Math.PI]), | |
| radius = d3.scale.linear().range([innerRadius, outerRadius]), | |
| color = d3.scale.category10().domain(d3.range(20)); | |
| var nodes = [ | |
| {x: 0, y: .1}, | |
| {x: 0, y: .9}, | |
| {x: 1, y: .2}, | |
| {x: 1, y: .3}, | |
| {x: 2, y: .1}, | |
| {x: 2, y: .8} | |
| ]; | |
| 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]} | |
| ]; | |
| var svg = d3.select("body").append("svg") | |
| .attr("width", width) | |
| .attr("height", height) | |
| .append("g") | |
| .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); | |
| 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); }); | |
| function degrees(radians) { | |
| return radians / Math.PI * 180 - 90; | |
| } | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment