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

Popular posts from this blog

google chrome - Developer tools - How to inspect the elements which are added momentarily (by JQuery)? -

angularjs - Showing an empty as first option in select tag -

php - Cloud9 cloud IDE and CakePHP -