rotate origin online svg coordinate-transformation

svg - origin - transform css



Cómo configurar el origen de la transformación en SVG (5)

Para escalar sin tener que usar la transformación de matrix :

transform="translate(cx, cy) scale(sx sy) translate(-cx, -cy)"

Y aquí está en CSS:

transform: translate(cxpx, cypx) scale(sx, sy) translate(-cxpx, -cypx)

Necesito cambiar el tamaño y rotar ciertos elementos en el documento SVG usando javascript. El problema es que, por defecto, siempre aplica la transformación alrededor del origen en (0, 0) - arriba a la izquierda.

¿Cómo puedo redefinir este punto de ancla de transformación?

Intenté usar el atributo de transform-origin , pero no afecta nada.

Así es como lo hice:

svg.getDocumentById(''someId'').setAttribute(''transform-origin'', ''75 240'');

No parece establecer el punto fundamental al punto que especifiqué, aunque puedo ver en Firefox que el atributo está configurado correctamente. Probé cosas como center bottom y 50% 100% con y sin paréntesis. Nada funcionó hasta ahora.

¿Alguien puede ayudar?


Para rotar use transform="rotate(deg, cx, cy)" , donde deg es el grado que desea rotar y (cx, cy) define el centro de rotación.

Para escalar / redimensionar, debe traducir por (-cx, -cy), luego escalar y luego traducir de nuevo a (cx, cy). Puedes hacer esto con una transformación matricial :

transform="matrix(sx, 0, 0, sy, cx-sx*cx, cy-sy*cy)"

Donde sx es el factor de escala en el eje x, sy en el eje y.


Si eres como yo y quieres hacer panorámicas y luego hacer zoom con origen de transformación, necesitarás un poco más.

// <g id="view"></g> var view = document.getElementById("view"); var state = { x: 0, y: 0, scale: 1 }; // Origin of transform, set to mouse position or pinch center var oX = window.innerWidth/2; var oY = window.innerHeight/2; var changeScale = function (scale) { // Limit the scale here if you want // Zoom and pan transform-origin equivalent var scaleD = scale / state.scale; var currentX = state.x; var currentY = state.y; // The magic var x = scaleD * (currentX - oX) + oX; var y = scaleD * (currentY - oY) + oY; state.scale = scale; state.x = x; state.y = y; var transform = "matrix("+scale+",0,0,"+scale+","+x+","+y+")"; //var transform = "translate("+x+","+y+") scale("+scale+")"; //same view.setAttributeNS(null, "transform", transform); };

Aquí está funcionando: http://forresto.github.io/dataflow-prototyping/react/


Si puede usar un valor fijo (no "centro" o "50%"), puede usar CSS en su lugar:

-moz-transform-origin: 25px 25px; -ms-transform-origin: 25px 25px; -o-transform-origin: 25px 25px; -webkit-transform-origin: 25px 25px; transform-origin: 25px 25px;

Algunos navegadores (como Firefox) no manejarán los valores relativos correctamente.


Tuve un problema similar. Pero estaba usando D3 para posicionar mis elementos, y quería que la transformación y la transición fueran manejadas por CSS. Este era mi código original, que obtuve trabajando en Chrome 65:

//... this.layerGroups.selectAll(''.dot'') .data(data) .enter() .append(''circle'') .attr(''transform-origin'', (d,i)=> `${valueScale(d.value) * Math.sin( sliceSize * i)} ${valueScale(d.value) * Math.cos( sliceSize * i + Math.PI)}`) //... etc (set the cx, cy and r below) ...

Esto me permitió establecer los valores de cx , cy y transform-origin en javascript utilizando los mismos datos.

PERO esto no funcionó en Firefox! Lo que tenía que hacer era envolver el circle en la etiqueta g y translate usando la misma fórmula de posicionamiento de arriba. A continuación, agregué el circle en la etiqueta g , y establecí sus valores de cx y cy en 0 . A partir de ahí, transform: scale(2) se escalaría desde el centro como se esperaba. El código final se veía así.

this.layerGroups.selectAll(''.dot'') .data(data) .enter() .append(''g'') .attrs({ class: d => `dot ${d.metric}`, transform: (d,i) => `translate(${valueScale(d.value) * Math.sin( sliceSize * i)} ${valueScale(d.value) * Math.cos( sliceSize * i + Math.PI)})` }) .append(''circle'') .attrs({ r: this.opts.dotRadius, cx: 0, cy: 0, })

Después de hacer este cambio, cambié mi CSS para enfocar el circle lugar del .dot , para agregar la transform: scale(2) . Ni siquiera necesito utilizar transform-origin .

NOTAS:

  1. Estoy usando d3-selection-multi en el segundo ejemplo. Esto me permite pasar un objeto a .attrs lugar de repetir .attr para cada atributo.

  2. Al usar un literal de plantilla de cadena, tenga en cuenta los saltos de línea como se ilustra en el primer ejemplo. Esto incluirá una nueva línea en la salida y puede romper su código.