2012-06-11 3 views
8

Ich bin in den frühen Phasen eines JS-Projekts. Alles läuft gut bis auf die Positionierung einer Form. Die fragliche Form ist ein teal Diamant (Quadrat um 45 Grad gedreht). Ich kann den Platz auf dem Bildschirm kein Problem, aber wenn ich hinzufügen:d3.js Odd Rotation Verhalten

.attr("transform", "rotate(45)") 

das Quadrat dreht richtig, sondern verschiebt sich in Richtung des linken Teil des Bildschirms, wie folgt aus:

enter image description here

Ich bin mir nicht sicher, was das verursacht. Wenn es hilft, ist hier ein Teil des Codes, der dieses Ergebnis geführt:

var svg = d3.select("body") 
      .append("svg") 
      .attr("width", w) 
      .attr("height", h); 
     svg 
      .append("rect") 
      .attr("transform", "rotate(45)") 
      .attr("x", 250) 
      .attr("height", w/10) 
      .attr("width", w/10) 
      .attr("fill", "teal") 

Hinweis: Wenn ich die „y“ in Attribute gesetzt, verschwindet das Quadrat vollständig.

Was verursacht das? Habe ich etwas falsch gemacht, das ich einfach nicht sehen kann?

Antwort

15

Wenn Sie das Rect rotieren, drehen Sie auch sein Koordinatensystem. Wenn Sie es später 250 entlang der x-Achse bewegen, bewegen Sie es tatsächlich 250 Einheiten entlang einer 45-Grad-Achse - das Ergebnis der Drehung.

In der Regel, wenn Sie ein transform Attribut wie Sie für rotate eingeführt haben, sollten Sie alle Ihre Transformation über dieses Attribut tun. Sie müssen also translate anstelle des Attributs "x" verwenden. Dann würde es so aussehen:

svg 
    .append("rect") 
    .attr("transform", "translate(250, 0) rotate(45)") 
    // remove this: .attr("x", 250) 
    .attr("height", w/10) 
    ... 

Dies bringt Sie die Ergebnisse, die ich denke, Sie suchen. Beachten Sie, dass die Reihenfolge der Transformationen hier von Bedeutung ist: Wenn Ihre Transformation "rotate(45) translate(250, 0)" war (d. H. Zuerst rotieren und dann übersetzen), erhalten Sie die gleichen falschen Ergebnisse, die Sie zuvor erhalten haben. Das liegt daran, dass beim ersten Drehen die Übersetzung wie zuvor entlang einer gedrehten X-Achse erfolgt.

+0

Ahhh Sie haben absolut Recht. Danke vielmals. Jetzt brauche ich die Form genau in der Mitte.Mit dem Pythagoräischen Theorm habe ich die Länge des Querschnitts gefunden und durch 2 geteilt. Das Ergebnis dieser Gleichung ist, was ich als y-Koordinate in meiner translate -Anweisung einstellen möchte (subtrahiert von der Leinwandhöhe/2 natürlich). . Es scheint, als könnte ich hier keine Variablen verwenden. Weißt du, wie ich das machen könnte? – 1080p

+2

Sie müssen Pythagoras nicht verwenden, solange Sie die Transformation in der richtigen Reihenfolge durchführen. Angenommen, 'w' und' h' sind die Zeichenflächengröße, und 'rw' und' rh' sind die Größe des Rect. Dies sollte tun, was Sie fragen: '.attr (" transform "," translate ("+ (w/2) + "," + (h/2) + ") rotieren (45) übersetzen (" + (-rw/2) + "," + (-rh/2) + ")". Mit anderen Worten Bewegen Sie sich zuerst oben links von rect zur Mitte, dann drehen Sie 45, dann zurück zur Halb- und zur halben Höhe von rect - entlang der 45-Grad-Achse -, die es zentriert Wenn Canvas 300x300 und Rect ist 100x100: ' "translate (150,150) rotate (45) translate (-50, -50)" ' – meetamit

+0

Interessant. Ich habe bereits Pythagoras in meinem Code eingerichtet, aber wenn Ihre Methode schneller ist, kann ich sie austauschen. Vielen Dank für all die – 1080p

11

In SVG müssen Sie den Ursprung Transformation gesetzt, um es von der Mitte zu drehen zu bekommen, wie ...

.attr("transform", "rotate(45, 250, 100)"); 

Wo 250, 100 ist die x- und y-Position Ihres rect minus es ist Radius. Dass sie alle zusammen würde es aussehen ...

var svg = d3.select("body") 
      .append("svg") 
      .attr("width", 400) 
      .attr("height", 300); 
     svg 
      .append("rect") 
      .attr("transform", "rotate(30,"+ (diamond.x+diamond.width/2) + ","+ (diamond.y+diamond.width/2) +")") 
      .attr("x", diamond.x) 
      .attr("y", diamond.y) 
      .attr("height", diamond.width) 
      .attr("width", diamond.width) 
      .attr("fill", "teal")​ 

können Sie eine Demo sehen hier:

http://jsfiddle.net/uwM8u/

+0

Ich habe bereits die Antwort für die Rotation erhalten, aber Ihr Codeausschnitt half mir sehr bei der Syntax für das rotate-Attribut Vielen Dank – 1080p

+0

danke Ich hatte Probleme, sie um ihre Mitte zu drehen. Sehr hilfreich. – greg

0

hier ein Ansatz unterscheidet sich etwas von der Antwort Duopixel gab. Hier wiederholen Sie nicht die Berechnungen für X und Y. In Duopixels Beispiel ist das eine triviale Verbesserung, da er lediglich auf eine Struktur verweist. Es ist oft der Fall, dass X und Y Funktionen sind und ich möchte das Logging nicht an zwei Stellen beibehalten. Mit diesem Ansatz können Sie X und Y als Knoten festlegen und dann in der Mitte des Knotens rotieren.

Sie können feststellen, dass Sie nach der Drehung noch die endgültige Position optimieren möchten, was mit einer anderen Transformation möglich ist, oder im Fall von TEXT können Sie dx, dy verwenden.

svgNode.attr("transform", function (d) { 

        var w = +d3.select(this).attr("x") + (this.getBBox().width/2) ; 
        var h = +d3.select(this).attr("y") + (this.getBBox().height/2); 

        return "rotate(90," + w + "," + h + ")"; 

       })