2012-06-11 21 views
8

Sono alle prime fasi di un progetto JS. Tutto sta andando bene finora tranne che per il posizionamento di una forma. La forma in questione è un diamante verde acqua (quadrato ruotato di 45 gradi). Posso ottenere il quadrato sullo schermo non è un problema, ma quando ho aggiungere:d3.js Comportamento anomalo rotazione

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

piazza ruota correttamente, ma si sposta verso la parte sinistra dello schermo, in questo modo:

enter image description here

Non sono sicuro di cosa stia causando questo. Se aiuta, qui è parte del codice che ha prodotto questo risultato:

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") 

Nota: Se metto la "y" attributo, la piazza scompare completamente.

Che cosa sta causando questo? Ho fatto qualcosa di sbagliato che non riesco a vedere?

risposta

15

Quando si ruota il rettangolo, si ruota anche il suo sistema di coordinate. Quindi, quando in seguito lo sposti 250 lungo l'asse x, lo stai effettivamente spostando di 250 unità lungo un asse di 45 gradi - il risultato della rotazione.

Di norma, quando si introduce un attributo transform come per lo rotate, è necessario eseguire tutta la trasformazione tramite questo attributo. Pertanto, è necessario utilizzare translate anziché utilizzare l'attributo "x". Quindi sarebbe simile a questo:

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

Questo ottiene i risultati che penso tu stia cercando. Ora nota che l'ordine delle trasformazioni è importante qui: se la tua trasformazione è stata "rotate(45) translate(250, 0)" (vale a dire prima ruotare e poi tradurre), otterresti lo stesso risultato sbagliato che avevi prima. Questo perché quando si ruota per primo, la traduzione avviene, come prima, lungo un asse x ruotato.

+0

Ahhh hai assolutamente ragione. Molte grazie. Quindi ora ho bisogno che la forma sia esattamente al centro.Usando il Teor di Pitagora, ho trovato la lunghezza della sezione trasversale e l'ho divisa per 2. Il risultato di questa equazione è ciò che voglio impostare come coordinata y nella mia dichiarazione di traslazione (sottratta dall'altezza della tela/2 ovviamente) . Sembra come se non posso usare le variabili qui però. Sai come potrei farlo? – 1080p

+2

Non è necessario utilizzare Pythagorean, a condizione che la trasformazione avvenga nell'ordine corretto. Supponendo che 'w' e' h' siano le dimensioni del quadro, e 'rw' e' rh' sono le dimensioni di Rect, questo dovrebbe fare ciò che stai chiedendo: '.attr (" transform "," translate ("+ (w/2) + "," + (h/2) + ") ruota (45) translate (" + (-rw/2) + "," + (-rh/2) + ")" '. In altre parole , prima muovere in alto a sinistra del rect al centro, quindi ruotare 45, quindi tornare indietro a metà larghezza e a metà altezza di rect - lungo 45 gradi asse - che lo centra.Se il canvas è 300x300 e il rect è 100x100: ' "translate (150,150) ruotare (45) translate (-50, -50)" ' – meetamit

+0

Interessante. Ho già installato Pythagorean nel mio codice, ma se il tuo metodo è più veloce, posso scambiarlo. Grazie mille per tutti aiuto – 1080p

11

In SVG è necessario impostare l'origine di trasformazione per farlo ruotare dal centro, come ad esempio ...

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

Dove 250, 100 è la posizione xey del vostro rect meno che sia il raggio. Mettere tutto insieme sarebbe simile ...

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")​ 

è possibile visualizzare una demo qui:

http://jsfiddle.net/uwM8u/

+0

Hai già la risposta per la rotazione, ma il tuo frammento di codice mi ha aiutato molto con la sintassi per l'attributo di rotazione.Grazie mille – 1080p

+0

Grazie. Ho avuto problemi a farli ruotare attorno al loro centro. – greg

0

Ecco un approccio leggermente diverso dalla risposta Duopixel ha dato. Qui non stai ripetendo i calcoli per X e Y. Nell'esempio di Duopixel, è un miglioramento insignificante dal momento che sta semplicemente facendo riferimento a una struttura. Spesso accade che X e Y siano funzioni e non vorrei mantenere quella registrazione in due punti. Questo approccio consente di impostare X e Y un nodo, quindi ruotare sul centro di detto nodo.

Potresti scoprire che dopo la rotazione, vuoi ancora modificare la posizione finale, che potrebbe essere eseguita con un'altra trasformazione, oppure, nel caso di TEXT, puoi usare dx, dy.

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 + ")"; 

       })