Comment puis-je ajouter un zoom à l'exemple de l'arbre repliable d3?

J'essaie d'ajouter une fonction de zoom à l' exemple de l' arbre déplaçable d3, mais je ne peux pas le faire fonctionner. Je sais qu'il y a eu une question à ce sujet ici et même si cela semble approfondi, mes changements ne fonctionnent pas. La seule chose que je reçois est une page blanche. Probablement à faire avec le fait que je suis plutôt nouveau avec javascript / d3. Voici mon code.

<!DOCTYPE html> <meta charset="utf-8"> <style> svg { pointer-events: all; } .node { cursor: pointer; } .node circle { fill: #fff; stroke: steelblue; stroke-width: 1.5px; } tree { pointer-events: all; } .node text { font: 12px sans-serif; } .link { fill: none; stroke: #ccc; stroke-width: 1.5px; } </style> <body> <script src="d3.v3.min.js"></script> <script> var margin = {top: 20, right: 120, bottom: 20, left: 120}, width = 1500 - margin.right - margin.left, height = 800 - margin.top - margin.bottom; var i = 0, duration = 750, root; var tree = d3.layout.tree() .size([height, width]); var diagonal = d3.svg.diagonal() .projection(function(d) { return [dy, dx]; }); var svg = d3.select("body").append("svg") .attr("width", width + margin.right + margin.left) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") d3.json("flare.json", function(error, flare) { root = flare; root.x0 = height / 2; root.y0 = 0; function collapse(d) { if (d.children) { d._children = d.children; d._children.forEach(collapse); d.children = null; } } root.children.forEach(collapse); update(root); }); d3.select(self.frameElement).style("height", "800px"); function update(source) { // Compute the new tree layout. var nodes = tree.nodes(root).reverse(), links = tree.links(nodes); // Normalize for fixed-depth. nodes.forEach(function(d) { dy = d.depth * 180; }); // Update the nodes… var node = svg.selectAll("g.node") .data(nodes, function(d) { return d.id || (d.id = ++i); }); // Enter any new nodes at the parent's previous position. var nodeEnter = node.enter().append("g") .attr("class", "node") .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }) .on("click", click); nodeEnter.append("circle") .attr("r", 1e-6) .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); nodeEnter.append("text") .attr("x", function(d) { return d.children || d._children ? -10 : 10; }) .attr("dy", ".35em") .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; }) .text(function(d) { return d.name; }) .style("fill-opacity", 1e-6); // Transition nodes to their new position. var nodeUpdate = node.transition() .duration(duration) .attr("transform", function(d) { return "translate(" + dy + "," + dx + ")"; }); nodeUpdate.select("circle") .attr("r", 4.5) .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); nodeUpdate.select("text") .style("fill-opacity", 1); // Transition exiting nodes to the parent's new position. var nodeExit = node.exit().transition() .duration(duration) .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; }) .remove(); nodeExit.select("circle") .attr("r", 1e-6); nodeExit.select("text") .style("fill-opacity", 1e-6); // Update the links… var link = svg.selectAll("path.link") .data(links, function(d) { return d.target.id; }); // Enter any new links at the parent's previous position. link.enter().insert("path", "g") .attr("class", "link") .attr("d", function(d) { var o = {x: source.x0, y: source.y0}; return diagonal({source: o, target: o}); }); // Transition links to their new position. link.transition() .duration(duration) .attr("d", diagonal); // Transition exiting nodes to the parent's new position. link.exit().transition() .duration(duration) .attr("d", function(d) { var o = {x: source.x, y: source.y}; return diagonal({source: o, target: o}); }) .remove(); // Stash the old positions for transition. nodes.forEach(function(d) { d.x0 = dx; d.y0 = dy; }); d3.select("svg") .call(d3.behavior.zoom() .scaleExtent([0.5, 5]) .on("zoom", zoom)); } // Toggle children on click. function click(d) { if (d.children) { d._children = d.children; d.children = null; } else { d.children = d._children; d._children = null; } update(d); function zoom() { var scale = d3.event.scale, translation = d3.event.translate, tbound = -h * scale, bbound = h * scale, lbound = (-w + m[1]) * scale, rbound = (w - m[3]) * scale; // limit translation to thresholds translation = [ Math.max(Math.min(translation[0], rbound), lbound), Math.max(Math.min(translation[1], bbound), tbound) ]; d3.select(".drawarea") .attr("transform", "translate(" + translation + ")" + " scale(" + scale + ")"); } } </script> 

Pourquoi l'implémentation du zoom ne fonctionne-t-elle pas?

J'ai joué avec votre code un peu et j'ai trouvé plusieurs problèmes potentiels:

Selon l'endroit où vous l'utilisez, le chargement du fichier flare.json pourrait provoquer une erreur CORS (par exemple, si vous essayez de vous connecter à celui du github de Bostock). Vous pouvez intégrer l'objet json directement dans une variable «flare», puis simplement déplacer le code que vous avez dans la méthode d3.json () au bas du script et affecter la variable racine à la flambée.

 var flare = ...paste contents of flare.json here... ; 

Vos méthodes javascript sont définies dans un ordre où vous faites référence aux méthodes avant leur définition (vous devez déplacer le zoom et cliquer sur les méthodes avant la méthode de mise à jour):

 collapse(d){...} zoom(){...} click(){...} update(){...} 

Votre méthode de zoom fait référence à 'h', 'w' et 'm', qui ne sont définis nulle part. Je suppose qu'ils sont censés être la largeur, la hauteur et la marge:

 var zoom = function() { var scale = d3.event.scale, translation = d3.event.translate, tbound = -height * scale, bbound = height * scale, lbound = (-width + margin.right) * scale, rbound = (width - margin.left) * scale; 

Enfin, pour réparer le zoom, vous devez réparer la méthode de zoom de la manière suivante:

 var zoom = function() { var scale = d3.event.scale, translation = d3.event.translate, tbound = -height * scale, bbound = height * scale, lbound = (-width + margin.right) * scale, rbound = (width - margin.left) * scale; // limit translation to thresholds translation = [ Math.max(Math.min(translation[0], rbound), lbound), Math.max(Math.min(translation[1], bbound), tbound) ]; svg.attr("transform", "translate(" + translation + ")" + " scale(" + scale + ")"); } 

Notez que j'ai remplacé "select (". DrawArea ")" par "svg." Parce que vous souhaitez transformer l'élément g supérieur (ce qui est dans la variable "svg").

Juste FYI – Je ne pouvais pas vraiment travailler dans plnkr ou jsFiddle car il y a des erreurs d3 étranges en raison de la façon dont les variables / la portée de la fonction sont traitées dans plnkr et jsFiddle (voir ici ). C'est peut-être un problème que quelqu'un d'autre peut s'entendre. Mais voici le code dans son intégralité (moins la variable intégrée flare.json). J'ai géré ce code dans mon propre conteneur Tomcat et je peux faire un double clic sur l'arborescence. Vous voudrez peut-être jouer avec un zoom et un panoramique pour que l'arbre ne s'inspire pas des limites de la fenêtre visibile (en ce moment Si vous cliquez deux fois, cela fera un zoom, mais plus récent, de sorte que le côté gauche de l'arbre se trouve sur le côté de la fenêtre du navigateur).

 <!DOCTYPE html> <meta charset="utf-8"> <style> svg { pointer-events: all; } .node { cursor: pointer; } .node circle { fill: #fff; stroke: steelblue; stroke-width: 1.5px; } tree { pointer-events: all; } .node text { font: 12px sans-serif; } .link { fill: none; stroke: #ccc; stroke-width: 1.5px; } </style> <body> <script src="http://d3js.org/d3.v3.min.js"></script> <script> var margin = {top: 20, right: 120, bottom: 20, left: 120}, width = 1500 - margin.right - margin.left, height = 800 - margin.top - margin.bottom; var i = 0, duration = 750, root; var tree = d3.layout.tree() .size([height, width]); var diagonal = d3.svg.diagonal() .projection(function(d) { return [dy, dx]; }); var svg = d3.select("body").append("svg") .attr("width", width + margin.right + margin.left) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") d3.select(self.frameElement).style("height", "800px"); var collapse = function(d) { if (d.children) { d._children = d.children; d._children.forEach(collapse); d.children = null; } } var zoom = function() { var scale = d3.event.scale, translation = d3.event.translate, tbound = -height * scale, bbound = height * scale, lbound = (-width + margin.right) * scale, rbound = (width - margin.left) * scale; // limit translation to thresholds translation = [ Math.max(Math.min(translation[0], rbound), lbound), Math.max(Math.min(translation[1], bbound), tbound) ]; svg.attr("transform", "translate(" + translation + ")" + " scale(" + scale + ")"); } // Toggle children on click. var click = function(d) { if (d.children) { d._children = d.children; d.children = null; } else { d.children = d._children; d._children = null; } update(d); }; var update = function(source) { // Compute the new tree layout. var nodes = tree.nodes(root).reverse(), links = tree.links(nodes); // Normalize for fixed-depth. nodes.forEach(function(d) { dy = d.depth * 180; }); // Update the nodes… var node = svg.selectAll("g.node") .data(nodes, function(d) { return d.id || (d.id = ++i); }); // Enter any new nodes at the parent's previous position. var nodeEnter = node.enter().append("g") .attr("class", "node") .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }) .on("click", click); nodeEnter.append("circle") .attr("r", 1e-6) .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); nodeEnter.append("text") .attr("x", function(d) { return d.children || d._children ? -10 : 10; }) .attr("dy", ".35em") .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; }) .text(function(d) { return d.name; }) .style("fill-opacity", 1e-6); // Transition nodes to their new position. var nodeUpdate = node.transition() .duration(duration) .attr("transform", function(d) { return "translate(" + dy + "," + dx + ")"; }); nodeUpdate.select("circle") .attr("r", 4.5) .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); nodeUpdate.select("text") .style("fill-opacity", 1); // Transition exiting nodes to the parent's new position. var nodeExit = node.exit().transition() .duration(duration) .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; }) .remove(); nodeExit.select("circle") .attr("r", 1e-6); nodeExit.select("text") .style("fill-opacity", 1e-6); // Update the links… var link = svg.selectAll("path.link") .data(links, function(d) { return d.target.id; }); // Enter any new links at the parent's previous position. link.enter().insert("path", "g") .attr("class", "link") .attr("d", function(d) { var o = {x: source.x0, y: source.y0}; return diagonal({source: o, target: o}); }); // Transition links to their new position. link.transition() .duration(duration) .attr("d", diagonal); // Transition exiting nodes to the parent's new position. link.exit().transition() .duration(duration) .attr("d", function(d) { var o = {x: source.x, y: source.y}; return diagonal({source: o, target: o}); }) .remove(); // Stash the old positions for transition. nodes.forEach(function(d) { d.x0 = dx; d.y0 = dy; }); d3.select("svg") .call(d3.behavior.zoom() .scaleExtent([0.5, 5]) .on("zoom", zoom)); }; d3.json("flare.json", function(json){ root = json; root.x0 = height / 2; root.y0 = 0; root.children.forEach(collapse); update(root); }); </script> 
 Zoom in&out with drag properties are very easy to appy with collapsible tree. Mainly we must add new version of d3 <script type="text/javascript" src="resources/d3.v3.js"></script> <script type="text/javascript" src="resources/d3.v3.min.js"></script> Are available in [http://d3js.org/][1] var vis = d3.select("#box").append("svg:svg") .attr("class","svg_container") .attr("width", w) .attr("height", h) .style("overflow", "scroll") .style("background-color","#EEEEEE") .append("svg:g") .attr("class","drawarea") .append("svg:g") .attr("transform", "translate(" + m[3] + "," + m[0] + ")"); d3.select("svg") //applying zoom in&out for svg .call(d3.behavior.zoom() .scaleExtent([0.5, 5]) .on("zoom", zoom)); function zoom() { //zoom in&out function var scale = d3.event.scale, translation = d3.event.translate, tbound = -h * scale, bbound = h * scale, lbound = (-w + m[1]) * scale, rbound = (w - m[3]) * scale; // limit translation to thresholds translation = [ Math.max(Math.min(translation[0], rbound), lbound), Math.max(Math.min(translation[1], bbound), tbound) ]; d3.select(".drawarea") .attr("transform", "translate(" + translation + ")" + " scale(" + scale + ")"); }