javascript - Hierarchical Edge Bundling - Automatically Generated Arcs in Radial Dendogram and Color -
back in october 2012, question posed ( d3.js - how automatically calculate arc lengths in radial dendrogram ) on how generate arcs in radial dendogram denote groups. user "wceo" posted elegant solution works well.
however, possible change color of each arc individually, rather have them same color? trying...
var color = d3.scale.category20();
... and...
var groupdata = svg.selectall("g.group") .data(nodes.filter(function(d) { return (d.key=='400' || d.key == '500' || d.key == '600' || d.key == 'current_missions' || d.key == 'future_missions') && d.children; })) .enter().append("group") .attr("class", "group") .attr("fill", function(d) { return color(d.group); });
... returns each of 5 arcs same color.
(i apologize not responding original topic. apparently don't have required 50 reputation so.)
(edited include entire sample code)
var w = 1800, h = 1600, rx = w / 2, ry = h / 2, m0, rotate = 0 pi = math.pi; var splines = []; var cluster = d3.layout.cluster() .size([360, ry - 400]) .sort(function(a, b) { return d3.ascending(a.key, b.key); }); var bundle = d3.layout.bundle(); var line = d3.svg.line.radial() .interpolate("bundle") .tension(.85) .radius(function(d) { return d.y; }) .angle(function(d) { return d.x / 180 * math.pi; }); // chrome 15 bug: <http://code.google.com/p/chromium/issues/detail?id=98951> var div = d3.select("#bundle") .style("top", "50px") .style("left", "50px") .style("width", w + "px") .style("height", w + "px") .style("position", "absolute"); var svg = div.append("svg:svg") .attr("width", w) .attr("height", w) .append("svg:g") .attr("transform", "translate(" + rx + "," + ry + ")"); var color = d3.scale.ordinal(); svg.append("svg:path") .attr("class", "arc") .attr("d", d3.svg.arc().outerradius(ry - 180).innerradius(0).startangle(0).endangle(2 * math.pi)) .on("mousedown", mousedown); d3.json("missions.json", function(classes) { var nodes = cluster.nodes(packages.root(classes)), links = packages.imports(nodes), splines = bundle(links); var path = svg.selectall("path.link") .data(links) .enter().append("svg:path") .attr("class", function(d) { return "link source-" + d.source.key + " target-" + d.target.key; }) .attr("d", function(d, i) { return line(splines[i]); }); var groupdata = svg.selectall("g.group") .data(nodes.filter(function(d) { return (d.key == '400' || d.key == '500' || d.key == '600' || d.key == 'current_missions' || d.key == 'future_missions') && d.children; })) .enter().append("group") .attr("class", "group"); var grouparc = d3.svg.arc() .innerradius(ry - 430) .outerradius(ry - 400) .startangle(function(d) { return (findstartangle(d.__data__.children)-2) * pi / 180;}) .endangle(function(d) { return (findendangle(d.__data__.children)+2) * pi / 180}); svg.selectall("g.arc") .data(groupdata[0]) .enter().append("svg:path") .attr("d", grouparc) .attr("class", "grouparc") .style("fill-opacity", 0.25); svg.selectall("g.node") .data(nodes.filter(function(n) { return !n.children; })) .enter().append("svg:g") .attr("class", "node") .attr("id", function(d) { return "node-" + d.key; }) .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; }) .append("svg:text") .attr("dx", function(d) { return d.x < 180 ? 2 : -2; }) .attr("dy", ".31em") .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; }) .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; }) .attr("color", function (d) { return (d.color) }) .text(function(d) { return d.key.replace(/_/g, ' '); }) .on("mouseover", mouseover) .on("mouseout", mouseout); d3.select("input[type=range]").on("change", function() { line.tension(this.value / 100); path.attr("d", function(d, i) { return line(splines[i]); }); }); }); d3.select(window) .on("mousemove", mousemove) .on("mouseup", mouseup); function mouse(e) { return [e.pagex - rx, e.pagey - ry]; } function mousedown() { m0 = mouse(d3.event); d3.event.preventdefault(); } function mousemove() { if (m0) { var m1 = mouse(d3.event), dm = math.atan2(cross(m0, m1), dot(m0, m1)) * 180 / math.pi; div.style("-webkit-transform", "translate3d(0," + (ry - rx) + "px,0)rotate3d(0,0,0," + dm + "deg)translate3d(0," + (rx - ry) + "px,0)"); } } function mouseup() { if (m0) { var m1 = mouse(d3.event), dm = math.atan2(cross(m0, m1), dot(m0, m1)) * 180 / math.pi; rotate += dm; if (rotate > 360) rotate -= 360; else if (rotate < 0) rotate += 360; m0 = null; div.style("-webkit-transform", "rotate3d(0,0,0,0deg)"); svg.attr("transform", "translate(" + rx + "," + ry + ")rotate(" + rotate + ")") .selectall("g.node text") .attr("dx", function(d) { return (d.x + rotate) % 360 < 180 ? 2 : -2; }) .attr("text-anchor", function(d) { return (d.x + rotate) % 360 < 180 ? "start" : "end"; }) .attr("transform", function(d) { return (d.x + rotate) % 360 < 180 ? null : "rotate(180)"; }); } } function mouseover(d) { svg.selectall("path.link.target-" + d.key) .classed("target", true) .each(updatenodes("source", true)); svg.selectall("path.link.source-" + d.key) .classed("source", true) .each(updatenodes("target", true)); } function mouseout(d) { svg.selectall("path.link.source-" + d.key) .classed("source", false) .each(updatenodes("target", false)); svg.selectall("path.link.target-" + d.key) .classed("target", false) .each(updatenodes("source", false)); } function updatenodes(name, value) { return function(d) { if (value) this.parentnode.appendchild(this); svg.select("#node-" + d[name].key).classed(name, value); }; } function cross(a, b) { return a[0] * b[1] - a[1] * b[0]; } function dot(a, b) { return a[0] * b[0] + a[1] * b[1]; } function findstartangle(children) { var min = children[0].x; children.foreach(function(d) { if (d.x < min) min = d.x; }); return min; } function findendangle(children) { var max = children[0].x; children.foreach(function(d) { if (d.x > max) max = d.x; }); return max; } (function() { packages = { // lazily construct package hierarchy class names. root: function(classes) { var map = {}; function find(name, data) { var node = map[name], i; if (!node) { node = map[name] = data || {name: name, children: []}; if (name.length) { node.parent = find(name.substring(0, = name.lastindexof("."))); node.parent.children.push(node); node.key = name.substring(i + 1); } } return node; } classes.foreach(function(d) { find(d.name, d); }); return map[""]; }, // return list of imports given array of nodes. imports: function(nodes) { var map = {}, imports = []; // compute map name node. nodes.foreach(function(d) { map[d.name] = d; }); // each import, construct link source target node. nodes.foreach(function(d) { if (d.imports) d.imports.foreach(function(i) { imports.push({source: map[d.name], target: map[i]}); }); }); return imports; } }; })();
Comments
Post a Comment