meine Lösung zu erklären:
Die grundlegenden Schritte sind wie folgt ablaufen:
- Update, um die Domänen die X- und Y-Skalen zum Pinselumfang
- die Achsen neu zeichnen
- berechnen Sie den Skalierungsfaktor und Transl ation für die
- Skalenlinien und übersetzen die Linie Container entsprechend
- Zurücksetzen der Bürste
anzumerken, dass 3 und 4 sind nur wenige Schritte erforderlich, da Sie die Waage nicht verwenden, alles zu zeichnen - eine bessere Ansatz wäre, zwei Punkte für jede Zeile als die Daten zu definieren, die an die Elemente gebunden sind, und dann die Maßstäbe zum Neuzeichnen zu verwenden. Dies würde den Code einfacher machen.
Mit Ihrem Ansatz ist es aber immer noch möglich. Um es zu erleichtern, habe ich ein paar Änderungen an Ihrem Code vorgenommen - insbesondere habe ich die verschiedenen verschachtelten g
Elemente mit verschiedenen Übersetzungen bereinigt und die Zeilen durch ihre x1
, x2
, y1
, y2
Attribute statt definiert durch Übersetzung der Container. Diese beiden Änderungen machen die gewünschte Funktionalität einfacher zu implementieren, da nur eine einzige Transformation stattfindet, bei der mehrere andere Transformationen nicht berücksichtigt werden müssen. Ich habe auch die Zeilen in mehreren g
Elementen verschachtelt, so dass sie leichter skaliert und übersetzt werden können.
Die Bürste Handler-Funktion sieht nun wie folgt aus:
// update scales, redraw axes
var extent = brush.extent();
x.domain(brush.empty() ? x2.domain() : [ extent[0][0], extent[1][0] ]);
y.domain(brush.empty() ? y2.domain() : [ extent[0][1], extent[1][1] ]);
xAxisG.call(xAxis);
yAxisG.call(yAxis);
Dieser Code sollte selbsterklärend sein - die Domänen der Waage aktualisiert entsprechend den aktuellen Umfang der Bürste und die Achsen neu gezeichnet .
// compute and apply scaling and transformation of the g elements containing the lines
var sx = (x2.domain()[1] - x2.domain()[0])/(x.domain()[1] - x.domain()[0]),
sy = (y2.domain()[1] - y2.domain()[0])/(y.domain()[1] - y.domain()[0]),
dx = -x2(x.domain()[0]) - x2.range()[0],
dy = -y2(y.domain()[1]) - y2.range()[1];
d3.selectAll("g.container")
.attr("transform", "translate(" + [sx * dx, sy * dy] + ")scale(" + [sx, sy] + ")");
Dies ist der schwierige Teil - auf der Grundlage der neuen Domänen der Waage, müssen wir den Umfang und die Übersetzung für die Linien berechnen. Die Skalierungsfaktoren sind einfach das Verhältnis des alten Ausmaßes zum neuen Ausmaß (beachte, dass ich Kopien der Skalen gemacht habe, die nicht modifiziert wurden), dh eine Zahl größer als 1. Die Übersetzung bestimmt die Verschiebung des (0,0) Koordinate und wird berechnet durch die Differenz der alten (0,0) Koordinate (ich erhalte diese aus dem Bereich der ursprünglichen Skalen) und die Position des neuen Domänenursprungs gemäß den ursprünglichen Skalen.
Wenn Sie die Translation und die Skalierung gleichzeitig anwenden, müssen wir die Offsets mit den Skalierungsfaktoren multiplizieren.
// reset brush
brush.clear();
d3.select(".brush").call(brush);
Schließlich löschen wir den Pinsel und setzen ihn zurück, um das graue Rechteck loszuwerden.
Vollständige Demo here.
Möchten Sie das vorhandene Diagramm mit der neuen gezoomten Ansicht überschreiben, ähnlich der [SE-Reputationsgrafik] (http://stackexchange.com/users/4536689/d3-gxt-java?tab=reputation)? – approxiblue
ja - Ich möchte genau wie im Beispiel beschrieben überschreiben. – somename
In Ihrem Beispiel haben Sie Zeilen mit der Rotation 30,45,60 erstellt ... ist das der reale Datensatz, oder haben Sie echte x (Datum) und y (Punkte) Werte wie hier http://stackexchange.com/users/4536689/d3-gxt-java? tab = reputation – Cyril