2012-06-11 36 views
8

Estoy en las primeras etapas de un proyecto de JS. Todo va bien hasta el momento, excepto por el posicionamiento de una forma. La forma en cuestión es un diamante verde azulado (cuadrado rotado 45 grados). Puedo conseguir la plaza en la pantalla sin ningún problema, pero cuando agrego:d3.js Odd Rotation Behavior

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

la plaza gira correctamente, pero se desplaza hacia la parte izquierda de la pantalla, así:

enter image description here

No estoy seguro de qué está causando esto. Si ayuda, aquí es una parte del código que produce este resultado:

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: Si pongo la "y" atributo en la plaza desaparece por completo.

¿Qué está causando esto? ¿Hice algo mal que simplemente no puedo ver?

Respuesta

15

Cuando gira el rect, también gira su sistema de coordenadas. Entonces, cuando más tarde lo mueves 250 a lo largo del eje x, en realidad lo estás moviendo 250 unidades a lo largo de un eje de 45 grados, el resultado de la rotación.

Como regla general, cuando introduce un atributo transform como lo hizo para rotate, debe hacer toda su transformación a través de este atributo. Por lo tanto, debe usar translate en lugar de usar el atributo "x". Entonces se vería así:

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

Esto le da los resultados que creo que usted está buscando. Ahora tenga en cuenta que el orden de las transformaciones importa aquí: si su transformación fue "rotate(45) translate(250, 0)" (es decir, primero gire y luego traduzca), obtendría los mismos resultados erróneos que obtuvo antes. Esto se debe a que cuando gira primero, su traducción ocurre, como antes, a lo largo de un eje x girado.

+0

Ahhh usted tiene toda la razón. Muchas gracias. Entonces ahora necesito que la forma esté exactamente en el centro.Utilizando la Teoría de Pitágoras, encontré la longitud de la sección transversal y la dividí por 2. El resultado de esa ecuación es lo que quiero establecer como la coordenada y en mi declaración de traducción (resta del alto de la lona/2 por supuesto) . Aunque parece que no puedo usar variables aquí. ¿Sabes cómo podría hacer eso? – 1080p

+2

No es necesario utilizar Pythagorean, siempre que realice la transformación en el orden correcto. Suponiendo que 'w' y' h' son el tamaño del lienzo, y 'rw' y' rh' son el tamaño del Rect, esto debería hacer lo que estás pidiendo: '.attr (" transform "," translate ("+ (w)/2) + "," + (h/2) + ") rotar (45) traducir (" + (-rw/2) + "," + (-rh/2) + ")" 'En otras palabras , primero mueva la parte superior izquierda de rect hacia el centro, luego gire 45, luego retroceda medio ancho y medio alto de rect - a lo largo de 45 grados eje - que lo centra. Si lienzo es 300x300 y rect es 100x100: ' "translate (150,150) rotate (45) translate (-50, -50)" ' – meetamit

+0

Interesante. Ya configuré el Pythagorean en mi código, pero si tu método es más rápido, puedo cambiarlo. Muchas gracias por todo ayuda. – 1080p

11

En SVG debe establecer el origen de transformación para conseguir que gire del centro, tales como ...

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

Dónde 250, 100 es la posición x e y de la rect menos Es radio. Poniendo todo junto que se vería así ...

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

Usted puede ver una demo aquí:

http://jsfiddle.net/uwM8u/

+0

Ya obtuve la respuesta para la rotación, pero el fragmento de código me ayudó mucho con la sintaxis para el atributo de rotación. Muchas gracias. – 1080p

+0

gracias. Estaba teniendo problemas para hacer que giren alrededor de su centro. Muy útil. – greg

0

Aquí es un enfoque ligeramente diferente de la respuesta Duopixel dio. Aquí no está repitiendo los cálculos para X e Y. En el ejemplo de Duopixel, es una mejora trivial ya que simplemente hace referencia a una estructura. A menudo es el caso de que X e Y sean funciones y no me gustaría mantener ese acceso en dos lugares. Este enfoque le permite establecer X e Y un nodo, luego girar en el centro de dicho nodo.

Es posible que después de la rotación, todavía desee ajustar la posición final, lo que podría hacerse con otra transformación, o en el caso de TEXT, puede usar 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 + ")"; 

       })