d3.js - d3 zoom not centering on mouse position with radial tree -
i'm trying apply standard d3 drag/zoom functionality radial tree layout.
the problem if define zoomhandler this...
svg.attr("transform","translate("+d3.event.translate+")scale("+d3.event.scale+")");
...then zoom follows mouse whole radial tree starts in wrong place on first zoom (i.e. (0,0)
coordinate).
whereas if define zoomhandler this...
svg.attr("transform", "translate(" + (w/2 + d3.event.translate[0]) + "," + (h/2 + d3.event.translate[1]) + ")scale(" + d3.event.scale + ")" );
...then tree behaves correctly zoom doesn't follow mouse (in fact in order zoom in/out on tree without moving mouse need positioned in 0,0 coordinate @ top-left of screen)
i appreciate topic that's been discussed before (i think notably here: using d3, can semantic zoom applied radial tree?), i'm still unclear how around problem hugely appreciate input who's resolved problem of getting radial tree both zoom towards mouse position, , remain anchored centre of screen @ same time. thanks!
here's complete code in detail...
<!doctype html> <html> <head> <title>demo</title> <script src="http://d3js.org/d3.v3.min.js"></script> <style> </style> </head> <body> <script> var w = 1200; var h = 1000; var data = [{'parent_id' : '1', 'items_count' : '2'} , {'parent_id' : '2', 'items_count' : '4'} , {'parent_id' : '3', 'items_count' : '3'} , {'parent_id' : '4', 'items_count' : '2'} , {'parent_id' : '5', 'items_count' : '1'} , {'parent_id' : '6', 'items_count' : '6'} , {'parent_id' : '7', 'items_count' : '2'} , {'parent_id' : '8', 'items_count' : '4'} , {'parent_id' : '9', 'items_count' : '5'} , {'parent_id' : '10', 'items_count' : '7'} ]; var treeradius = 300; var searchcircleradius = 60; var circleradiusscale = d3.scale.linear() .domain([0, d3.max(data, function(d) { return d.items_count; })]) .range([10, 40]); var datatree = { children: data.map(function(d) { return { parent_id: d.parent_id, items_count: d.items_count}; }) }; var tree = d3.layout.tree() .size([360, treeradius]); var mainsvg = d3.select("body").append("svg") .attr("width", w) .attr("height", h); var svg = mainsvg .append("g") .attr("transform", "translate(" + (w / 2) + "," + (h / 2) + ")"); var childgroupzoom = svg.append("g"); var zoomlistener = d3.behavior.zoom() .scaleextent([0.1, 1.75]) .on("zoom", zoomhandler); function zoomhandler() { //1) both of these, tree starts in centre of screen, drag works nicely, zoom doesn't follow mouse //childgroupzoom.attr("transform", "translate(" + (d3.event.translate[0]) + "," + (d3.event.translate[1]) + ") scale(" + d3.event.scale + ")"); childgroupzoom.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); //2) follows mouse on zoom jump top-left on first zoom/drag (because it's applied "svg" has translate applied)... //svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); //follows mouse on zoom starts @ wrong place //3) same first category - tree doesn't jump, zoom doesn't follow mouse //svg.attr("transform", "translate(" + (w/2 + d3.event.translate[0]) + "," + (h/2 + d3.event.translate[1]) + ")scale(" + d3.event.scale + ")" ); //starts in centre doesn't follow mouse! } zoomlistener(mainsvg); var nodes = tree.nodes(datatree); var basicnode = childgroupzoom.selectall(".node"); var node = basicnode .data(nodes) .enter().append("g") .attr("class", "node") .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ") translate(" + d.y + ")"; }); var outlinecircles = node.append("circle") .attr("r", function(d,i) { if (i<1) { return searchcircleradius; } else { return circleradiusscale(d.items_count); }}) .attr("stroke", "#0099ff") .attr("stroke-width", "3") .attr("transform", function(d) {return "rotate(" + (-d.x + 90) + ")";}); </script> </body> </html>
var draglistener = d3.behavior.drag() .on("drag", function() { dragx = d3.event.dx; dragy = d3.event.dy; }); mainsvg.call(draglistener); var dragging = 0; var dragx = 0, dragy = 0; draglistener.on("dragstart", function() { dragging = 1; }); draglistener.on("dragend", function() { dragging = 0; dragx = 0; dragy = 0; }); function zoomhandler() { var pos = d3.mouse(this); var scale = d3.event.scale; var trans = d3.transform(childgroupzoom.attr("transform")); var tpos = trans.translate; var tscale = trans.scale; var tx = tpos[0]; var ty = tpos[1]; var mx = pos[0] - w/2; var = pos[1] - h/2; var dx = (mx - tx - dragx)/tscale[0]; var dy = (my - ty - dragy)/tscale[1]; var dx2 = (mx - dx)/scale - dx; var dy2 = (my - dy)/scale - dy; var tform = "translate(" + dx + "," + dy + ")scale(" + scale + ")translate(" + dx2 + "," + dy2 + ")" childgroupzoom.attr("transform", tform); }
note: zoom handler being called framework on drag operations facilitating object movement virtue of dragx , dragy.
Comments
Post a Comment