d3.js - Dynamically Updating A D3 Treemap Datasource -
i think i'm missing obvious here. trying create treemap on button click go server , retrieve next level treemap...this necessary because treemap structure large , takes long calculate jumping 1 level @ time option have.
[note ie users, in example treemap node names don't appear working. try using chrome]
this code taken
http://bost.ocks.org/mike/treemap/
i'm using vizdata1.json "first" level , on mouse click i'm using vizdata2.json "second" level. can see 2 end overlapping. i've tried svg.exit() svg.clear() without luck.
i should note have tried sticky(false) suggestion post
does d3 treemap layout cached when root node passed it?
update: continue hunt have found example adds new nodes existing treemap. having trouble adapting logic treemap attempting fit logic has been heavily customized michael bostock - @mbostock allow nice breadcrumb trail bar @ top.
code snippet proves appending existing treemap nodes possible: http://jsfiddle.net/wb5jh/3/
also, stackoverflow forcing me post code because i'm linking plnkr have dumped script.js here rather not interact plunker
$(function() { var margin = { top: 20, right: 0, bottom: 0, left: 0 }, width = 960, height = 500, formatnumber = d3.format(",d"), transitioning; var x = d3.scale.linear() .domain([0, width]) .range([0, width]); var y = d3.scale.linear() .domain([0, height]) .range([0, height]); var treemap = d3.layout.treemap() .children(function (d, depth) { return depth ? null : d._children; }) .sort(function (a, b) { return a.value - b.value; }) .ratio(height / width * 0.5 * (1 + math.sqrt(5))) .round(false) .sticky(false); var svg = d3.select("#treemap") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.bottom + margin.top) .style("margin-left", -margin.left + "px") .style("margin.right", -margin.right + "px") .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") .style("shape-rendering", "crispedges"); var grandparent = svg.append("g") .attr("class", "grandparent"); grandparent.append("rect") .attr("y", -margin.top) .attr("width", width) .attr("height", margin.top); grandparent.append("text") .attr("x", 6) .attr("y", 6 - margin.top) .attr("dy", ".75em"); d3.json("vizdata1.json", function (root) { initialize(root); accumulate(root); layout(root); display(root); }); function initialize(root) { root.x = root.y = 0; root.dx = width; root.dy = height; root.depth = 0; } // aggregate values internal nodes. done // treemap layout, not here because of our custom implementation. // take snapshot of original children (_children) avoid // children being overwritten when when layout computed. function accumulate(d) { return (d._children = d.children) ? d.value = d.children.reduce(function (p, v) { return p + accumulate(v); }, 0) : d.value; } // compute treemap layout recursively such each group of siblings // uses same size (1×1) rather dimensions of parent cell. // optimizes layout current zoom state. note wrapper // object created parent node each group of siblings // parent’s dimensions not discarded recurse. since each group // of sibling laid out in 1×1, must rescale fit using absolute // coordinates. lets use viewport zoom. function layout(d) { if (d._children) { treemap.nodes({ _children: d._children }); d._children.foreach(function (c) { c.x = d.x + c.x * d.dx; c.y = d.y + c.y * d.dy; c.dx *= d.dx; c.dy *= d.dy; c.parent = d; layout(c); }); } } function display(d) { console.log(d); grandparent .datum(d.parent) .on("click", transition) .select("text") .text(name(d)); var g1 = svg.insert("g", ".grandparent") .datum(d) .attr("class", "depth"); var g = g1.selectall("g") .data(d._children) .enter().append("g"); g.filter(function (d) { return d._children; }) .classed("children", true) .on("click", transition); g.selectall(".child") .data(function (d) { return d._children || [d]; }) .enter().append("rect") .attr("class", "child") .call(rect); g.append("rect") .attr("class", "parent") .call(rect) .append("title") .text(function (d) { return formatnumber(d.value); }); g.append("foreignobject") .call(rect) .attr("class", "foreignobj") .append("xhtml:div") .attr("dy", ".75em") .html(function (d) { return d.name; }) .attr("class", "textdiv"); function transition(d) { if (transitioning || !d) return; transitioning = true; d3.json("vizdata2.json", function (root) { initialize(root); accumulate(root); layout(root); display(root); }); var g2 = display(d), t1 = g1.transition().duration(750), t2 = g2.transition().duration(750); // update domain after entering new elements. x.domain([d.x, d.x + d.dx]); y.domain([d.y, d.y + d.dy]); // enable anti-aliasing during transition. svg.style("shape-rendering", null); // draw child nodes on top of parent nodes. svg.selectall(".depth").sort(function (a, b) { return a.depth - b.depth; }); // fade-in entering text. g2.selectall("text").style("fill-opacity", 0); g2.selectall("foreignobject div").style("display", "none"); /*added*/ // transition new view. t1.selectall("text").call(text).style("fill-opacity", 0); t2.selectall("text").call(text).style("fill-opacity", 1); t1.selectall("rect").call(rect); t2.selectall("rect").call(rect); t1.selectall(".textdiv").style("display", "none"); /* added */ t1.selectall(".foreignobj").call(foreign); t2.selectall(".textdiv").style("display", "block"); /* added */ t2.selectall(".foreignobj").call(foreign); /* added */ // remove old node when transition finished. t1.remove().each("end", function () { svg.style("shape-rendering", "crispedges"); transitioning = false; }); } return g; } function text(text) { text.attr("x", function (d) { return x(d.x) + 6; }) .attr("y", function (d) { return y(d.y) + 6; }); } function rect(rect) { rect.attr("x", function (d) { return x(d.x); }) .attr("y", function (d) { return y(d.y); }) .attr("width", function (d) { return x(d.x + d.dx) - x(d.x); }) .attr("height", function (d) { return y(d.y + d.dy) - y(d.y); }); } function foreign(foreign) { /* added */ foreign.attr("x", function (d) { return x(d.x); }) .attr("y", function (d) { return y(d.y); }) .attr("width", function (d) { return x(d.x + d.dx) - x(d.x); }) .attr("height", function (d) { return y(d.y + d.dy) - y(d.y); }); } function name(d) { return d.parent ? name(d.parent) + "." + d.name : d.name; } });