D3 hat eine gerichtete Kraft Layout hier . Gibt es eine Möglichkeit, diesem Diagramm das Zoomen hinzuzufügen? Derzeit konnte ich das Mausradereignis erfassen, bin mir aber nicht sicher, wie ich die Neuzeichnungsfunktion selbst schreiben soll. Irgendwelche Vorschläge?
var vis = d3.select("#graph")
.append("svg:svg")
.call(d3.behavior.zoom().on("zoom", redraw)) // <-- redraw function
.attr("width", w)
.attr("height", h);
javascript
jquery
d3.js
zoom
force-layout
Legende
quelle
quelle
Antworten:
Update 04.06.14
Siehe auch die Antwort von Mike Bostock hier für Änderungen in D3 v.3 und dem zugehörigen Beispiel . Ich denke, dies ersetzt wahrscheinlich die Antwort unten.
Update 18.02.2014
Ich denke, die Antwort von @ ahaarnos ist vorzuziehen, wenn Sie möchten, dass das gesamte SVG schwenkt und zoomt. Die verschachtelten
g
Elemente in meiner Antwort unten sind wirklich nur erforderlich, wenn Sie nicht zoomende Elemente in derselben SVG haben (in der ursprünglichen Frage nicht der Fall). Wenn Sie tun , um das Verhalten zu einem anwendeng
Elemente, dann ein Hintergrundrect
oder ein ähnliches Element erforderlich , um sicherzustellen , dass dieg
Zeiger - Ereignisse empfängt.Ursprüngliche Antwort
Ich habe dies basierend auf dem Zoom-Pan-Transform- Beispiel zum Laufen gebracht - Sie können meine jsFiddle hier sehen: http://jsfiddle.net/nrabinowitz/QMKm3/
Es war etwas komplexer als ich gehofft hatte - Sie müssen mehrere
g
Elemente verschachteln , damit es funktioniert, das SVG-pointer-events
Attribut auf setzenall
und dann ein Hintergrundrechteck anhängen, um die Zeigerereignisse zu empfangen (andernfalls funktioniert es nur, wenn der Zeiger vorbei ist ein Knoten oder eine Verbindung). Dieredraw
Funktion ist vergleichsweise einfach und setzt lediglich eine Transformation auf das Innersteg
:var vis = d3.select("#chart") .append("svg:svg") .attr("width", w) .attr("height", h) .attr("pointer-events", "all") .append('svg:g') .call(d3.behavior.zoom().on("zoom", redraw)) .append('svg:g'); vis.append('svg:rect') .attr('width', w) .attr('height', h) .attr('fill', 'white'); function redraw() { console.log("here", d3.event.translate, d3.event.scale); vis.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); }
Dadurch wird das gesamte SVG effektiv skaliert, sodass auch die Strichbreite skaliert wird, wie beim Vergrößern eines Bildes.
Es gibt ein anderes Beispiel , das eine ähnliche Technik veranschaulicht.
quelle
body
Tag. Ich empfehle daher, sich die Frame-Quelle anzusehen und zu sehen, was Ihnen fehlt.zoom.scaleExtent()
Warum die verschachtelten
<g>
?Dieser Code unten hat bei mir gut funktioniert (nur einer
<g>
ohne zufälliges großes Weiß<rect>
:var svg = d3.select("body") .append("svg") .attr({ "width": "100%", "height": "100%" }) .attr("viewBox", "0 0 " + width + " " + height ) .attr("preserveAspectRatio", "xMidYMid meet") .attr("pointer-events", "all") .call(d3.behavior.zoom().on("zoom", redraw)); var vis = svg .append('svg:g'); function redraw() { vis.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); }
Wobei alle Elemente in Ihrem SVG an das
vis
Element angehängt werden .quelle
transformation
Attribut auf dasg
Element anzuwenden , nicht auf dassvg
Element.Die bereitgestellten Antworten funktionieren in D3 v2, jedoch nicht in v3. Ich habe die Antworten zu einer sauberen Lösung zusammengefasst und das v3-Problem mithilfe der hier angegebenen Antwort behoben : Warum bricht d3.js v3 mein Force-Diagramm, wenn das Zoomen implementiert wird, wenn v2 dies nicht tut?
Zuerst der Hauptcode. Dies ist eine bereinigte Version der Antwort von @ahaarnos:
var svg = d3.select("body") .append("svg") .attr("width", width) .attr("height", height) .call(d3.behavior.zoom().on("zoom", redraw)) .append('g'); function redraw() { svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); }
Jetzt können Sie schwenken und zoomen, aber Sie können keine Knoten ziehen, da die Schwenkfunktion die Ziehfunktion überschreibt. Also müssen wir das tun:
var drag = force.stop().drag() .on("dragstart", function(d) { d3.event.sourceEvent.stopPropagation(); // to prevent pan functionality from //overriding node drag functionality. // put any other 'dragstart' actions here });
Hier ist @nrabinowitz 'Geige, die geändert wurde, um diese sauberere Zoom-Implementierung zu verwenden, aber veranschaulicht, wie D3v3 das Ziehen von Knoten unterbricht: http://jsfiddle.net/QMKm3/718/
Und hier ist dieselbe Geige, die für D3v3 geändert wurde: http://jsfiddle.net/QMKm3/719/
quelle
Ich habe mein Diagramm ohne das zweite "svg: g" -Anhängen zum Laufen gebracht.
[...].attr("pointer-events", "all") .attr("width", width2) .attr("height", height2) .append('svg:g') .call(d3.behavior.zoom().on("zoom", redraw));
Der Rest ist der gleiche.
quelle
Ich habe eine Lösung für D3 Force Graced Graph mit Zoom-Option.
var m = [40, 240, 40, 240], width = 960, height = 700, root; var svg = d3.select("body").append("svg") .attr("class", "svg_container") .attr("width", width) .attr("height", height) .style("overflow", "scroll") .style("background-color", "#EEEEEE") .append("svg:g") .attr("class", "drawarea") .append("svg:g") .attr("transform", "translate(" + m[3] + "," + m[0] + ")"); //applying zoom in&out for svg d3.select("svg") .call(d3.behavior.zoom() .scaleExtent([0.5, 5]) .on("zoom", zoom)); //zooming function zoom() { //zoom in&out function var scale = d3.event.scale, translation = d3.event.translate, tbound = -height * scale, bbound = height * scale, lbound = (-width + m[1]) * scale, rbound = (width - 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 + ")"); }
quelle
Wenn Sie das Layout zoomen und schwenken möchten, ohne die Knotengröße zu ändern, versuchen Sie es unten. Sie können Knoten auch ziehen, ohne zu zittern. Dieser Code basiert auf dem ursprünglichen Force-Layout-Beispiel. Informationen zu Knoten- und Linkdaten finden Sie in den Originalbeispieldaten. http://bl.ocks.org/mbostock/4062045
Bitte beachten Sie die Variablen xScale und yScale, die Funktionen dragstarted (), dragged () und dragended (). Die Funktion tick () wurde ebenfalls geändert.
Sie können das Ergebnis unter http://steelblue.tistory.com/9 sehen. Die Sprache auf der Website ist Koreanisch. Das Ergebnis finden Sie jedoch leicht im dritten Beispiel auf der Seite.
var graph = { "nodes": [ { "name": "Myriel", "group": 1 }, { "name": "Napoleon", "group": 1 }, // ...... { "name": "Mme.Hucheloup", "group": 8 } ], "links": [ { "source": 1, "target": 0, "value": 1 }, { "source": 2, "target": 0, "value": 8 }, // ....... { "source": 76, "target": 58, "value": 1 } ] }; var width = 640, height = 400; var color = d3.scale.category20(); var xScale = d3.scale.linear() .domain([0, width]) .range([0, width]); var yScale = d3.scale.linear() .domain([0, height]) .range([0, height]); var zoomer = d3.behavior.zoom().x(xScale).y(yScale).scaleExtent([0.1, 8]).on("zoom", zoom); function zoom() { tick(); }; var drag = d3.behavior.drag() .origin(function (d) { return d; }) .on("dragstart", dragstarted) .on("drag", dragged) .on("dragend", dragended); function dragstarted(d) { d3.event.sourceEvent.stopPropagation(); d.fixed |= 2; } function dragged(d) { var mouse = d3.mouse(svg.node()); d.x = xScale.invert(mouse[0]); d.y = yScale.invert(mouse[1]); d.px = d.x; d.py = d.y; force.resume(); } function dragended(d) { d.fixed &= ~6; } var force = d3.layout.force() .charge(-120) .linkDistance(30) .size([width, height]); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); svg.call(zoomer); force .nodes(graph.nodes) .links(graph.links) .start(); var link = svg.selectAll(".link") .data(graph.links) .enter().append("line") .attr("class", "link") .style("stroke-width", function (d) { return Math.sqrt(d.value); }); var node = svg.selectAll(".node") .data(graph.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 5) .style("fill", function (d) { return color(d.group); }) .call(drag); node.append("title") .text(function (d) { return d.name; }); force.on("tick",tick); function tick(){ link.attr("x1", function (d) { return xScale(d.source.x); }) .attr("y1", function (d) { return yScale(d.source.y); }) .attr("x2", function (d) { return xScale(d.target.x); }) .attr("y2", function (d) { return yScale(d.target.y); }); node.attr("transform", function (d) { return "translate(" + xScale(d.x) + "," + yScale(d.y) + ")"; }); };
quelle