I am using a Partition tree as in this example to try and make a visualization for taxonomy trees. I tried to follow the code in the d3.js and the scripting in the html. It looks like the Layout and onclick event just increases the ’rect’ sizes and then clips it to fit in the same size SVG element. Would it be possible to use a polylinear scale on the x axis so I can keep each parent nodes on screen as I go deeper into the tree?
For example if the layout was 160px wide and four columns across each column is 40px wide. I’d like the tree to start with the first column 10px wide which makes the others fill up the 150px at 50px each. If the next column was clicked then the domain and range would change so that the 2 left columns would be 10px each and the others would be 70px etc.
I tried changing the range from ([0, 160]) to ([0, 10, 160]) and the domain to ([0, .25 ,1]). Is this the right approach? The positions changed but not the widths. I would probably want to change the range and domain depending on the depth.
Edit Here is the code from the html script. I was thinking of changing the code below to something like
var parentcolumns = 30;
var numberleftcolumns = 0.25;
x = d3.scale.linear().domain([0, numberleftcolumns, 1]).range([0, parentcolumns, h]),
The numbers I used in the example were just to help discribe the problem. Here the width is 1120px.
<script type="text/javascript">
var w = 1120,
h = 600,
x = d3.scale.linear().range([0, w]),
y = d3.scale.linear().range([0, h]);
var vis = d3.select("#body").append("div")
.attr("class", "chart")
.style("width", w + "px")
.style("height", h + "px")
.append("svg:svg")
.attr("width", w)
.attr("height", h);
var partition = d3.layout.partition()
.value(function(d) { return d.size; });
d3.json("http://localhost:8080/flare.json", function(root) {
console.log("loadedJson:",root);
var g = vis.selectAll("g")
.data(partition.nodes(root))
.enter().append("svg:g")
.attr("transform", function(d) { return "translate(" + x(d.y) + "," + y(d.x) + ")"; })
.on("click", click);
var kx = w / root.dx,
ky = h / 1;
g.append("svg:rect")
.attr("width", root.dy * kx)
.attr("height", function(d) { return d.dx * ky; })
.attr("class", function(d) { return d.children ? "parent" : "child"; });
g.append("svg:text")
.attr("transform", transform)
.attr("dy", ".35em")
.style("opacity", function(d) { return d.dx * ky > 12 ? 1 : 0.15; })
.text(function(d) { return d.name; })
d3.select(window)
.on("click", function() { click(root); })
function click(d) {
if (!d.children) return;
kx = (d.y ? w - 40 : w) / (1 - d.y);
ky = h / d.dx;
x.domain([d.y, 1]).range([d.y ? 40 : 0, w]);
y.domain([d.x, d.x + d.dx]);
var t = g.transition()
.duration(d3.event.altKey ? 7500 : 750)
.attr("transform", function(d) { return "translate(" + x(d.y) + "," + y(d.x) + ")"; });
t.select("rect")
.attr("width", d.dy * kx)
.attr("height", function(d) { return d.dx * ky; });
t.select("text")
.attr("transform", transform)
.style("opacity", function(d) { return d.dx * ky > 12 ? 1 : 0; });
d3.event.stopPropagation();
}
function transform(d) {
return "translate(8," + d.dx * ky / 2 + ")";
}
});
</script>
I would have to rewrite the onclick function to deal with the domain and range changes and alter my parentcolumns each time.