问题
I am trying to implement a version of the SVG Semantic Zoom and Pan example for D3.js, found here. I am trying to do this with a Dendrogram / tree (example here), as recommended by Mike Bostock (here). The goal is like this jsFiddle that one of the other threads mentioned, except without the weird node / path unlinking behavior. My personal attempt is located here.
I was getting an error in Firebug with Mike's code, about "cannot translate(NaN,NaN)", so I changed the code in the zoom function to what is shown below. However, the behavior is weird. Now 1) my paths don't zoom / move, and 2) I can only pan the nodes from Lower Right--Upper Left (if I try panning from Lower Left--Upper Right, the nodes still move along the LR-UL direction).
var vis = d3.select("#tree").append("svg:svg")
.attr("viewBox", "0 0 600 600")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")")
.call(d3.behavior.zoom().x(x).y(y).scaleExtent([1,8]).on("zoom",zoom));
// zoom in / out
function zoom() {
var nodes = vis.selectAll("g.node");
nodes.attr("transform", transform);
}
function transform(d) {
return "translate(" + x(d.y) + "," + y(d.x) + ")";
}
I tried following the other solutions given in the Google Groups thread mentioned above and the jsFiddle, but I don't make much progress. Including the path links from the jsFiddle in my code and a translate() function lets me scale the paths--except 1) they flip vertically (somewhere x and y transposition isn't working right); 2) the paths don't zoom at the same rate as the nodes (perhaps related to #1), so they become "unlinked"; and 3) when I pan, the paths now pan in all directions, but the nodes don't move. When I click on a node to expand the tree, the paths re-adjust and fix themselves, so the update code seems to work better (but I don't know how to identify / copy the working parts of that). See my code here.
function zoom(d) {
var nodes = vis.selectAll("g.node");
nodes.attr("transform", transform);
// Update the links...
var link = vis.selectAll("path.link");
link.attr("d", translate);
}
function transform(d) {
return "translate(" + x(d.y) + "," + x(d.x) + ")";
}
function translate(d) {
var sourceX = x(d.target.parent.y);
var sourceY = y(d.target.parent.x);
var targetX = x(d.target.y);
var targetY = (sourceX + targetX)/2;
var linkTargetY = y(d.target.x0);
var result = "M"+sourceX+","+sourceY+" C"+targetX+","+sourceY+" "+targetY+","+y(d.target.x0)+" "+targetX+","+linkTargetY+"";
//console.log(result);
return result;
My questions are:
- Are there any working examples of zoom / pan on a Dendrogram / tree that I can look at?
- With the code I have above, can anyone identify where / how the paths are getting flipped? I have tried various permutations within the translate() function of drawing the SVG Cubic Bezier curve, but nothing seems to work right. Again, my jsFiddle is here.
- Any troubleshooting tips or ideas why panning only partially works?
Thank you everyone for your help!
回答1:
You had a pretty good implementation that was derailed by one major typo:
function transform(d) {
return "translate(" + x(d.y) + "," + x(d.x) + ")";
}
Should have been
function transform(d) {
return "translate(" + x(d.y) + "," + y(d.x) + ")";
}
To have your paths not flip you should have probably not reversed the y-axis:
y = d3.scale.linear().domain([0, h]).range([h, 0])
changed to
y = d3.scale.linear().domain([0, h]).range([0, h])
Fixes are here: http://jsfiddle.net/6kEpp/2/. But for future reference, you should probably have your x-axis operate on x-values, and y-axis operate on y-values, or you're just going to really confuse yourself.
Final remarks to polish your implementation:
- There is a little bit of jumpiness in the bezier drawing going from the default rendering (or right after opening/closing a node) to the zoom implementation. You just need to make those the same bezier function, and it will feel a lot better when you play with it.
- You need to update the zoom vector after the graph redraws itself, based on the relative movement of existing nodes. Otherwise, there will be a sudden jump when you try to zoom again after opening/closing a node.
来源:https://stackoverflow.com/questions/14666543/d3-js-semantic-zoom-and-pan-example-not-working