origin how girar matrix svg transform inkscape

matrix - how - svg transform css



Aplanar transformaciones de matrices SVG en Inkscape (5)

Tengo un archivo SVG de imágenes prediseñadas creado originalmente en Inkscape, y estoy haciendo modificaciones para usarlo en un juego JavaScript de Windows 8. Contiene numerosas instancias de una ruta con una transformación de matriz aplicada en un grupo circundante, como este:

<g transform="matrix(0.443,0.896,-0.896,0.443,589.739,-373.223)"> <path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" /> </g>

Quiero aplanar esa transformación aplicándola de antemano a la ruta en Inkscape, para reducir el trabajo del navegador durante la animación. Sin embargo, cuando conecto los 6 valores de matriz en los parámetros ABCDEF en Inkscape y los aplico, le da a la ruta una rotación y escalado completamente diferentes a los que hace el motor IE10.

He comprobado en numerosas ocasiones que tengo los 6 valores mapeados correctamente. ¿Qué estoy haciendo mal?

EDITAR: OK, aquí están las capturas de pantalla antes y después de IE10 e Inkscape. Para el caso de IE10, el SVG reside directamente dentro del cuerpo de un documento HTML vacío (la representación es exactamente la misma en Firefox). En Inkscape, simplemente abrí el archivo "anterior" SVG que contiene solo el elemento de ruta, seleccioné la ruta y conecté los 6 valores de transformación de matriz en Objeto> Transformar> Matriz. Sé muy poco sobre las matrices, solo quiero poder aplicar estas transformaciones de la misma manera que lo hace el navegador, y lo ideal es entender por qué hay una diferencia en Inkscape. Gracias.


Respuesta corta

Al escribir los parámetros de la matriz de transformación en Inkscape, asegúrese de marcar "Editar matriz actual", ya que si aplica una nueva matriz de transformación a un objeto, en realidad está multiplicando esta nueva matriz por la matriz de transformación existente del objeto, por lo que asegúrese de editarlo en su lugar.

Respuesta larga

Cómo volver a calcular todo usted mismo

Primero intentemos y comprendamos un poco las matrices de transformación. Una matriz de transformación es una herramienta rápida e inteligente para aplicar transformaciones afines (transformación que conserva líneas rectas) a un vector.
Entonces, si tienes un vector (por ejemplo, coordenadas 2d) y una matriz de transformación, y multiplicas los dos juntos, terminarás con las coordenadas transformadas, con las transformaciones definidas en la matriz de transformación, aplicadas.

Calcular x'' e y'' se hace así:

x'' = a*x + c*y + e y'' = b*x + d*y + f

A continuación, tenemos que entender el formato svg un poco.
De acuerdo con la especificación w3c svg, la transformación de matrix toma exactamente esos 6 parámetros (a, b, c, d, e, f) como argumentos.
Por lo tanto, de tu ejemplo,

<g transform="matrix(0.443,0.896,-0.896,0.443,589.739,-373.223)">

tenemos los siguientes parámetros de matriz de transformación:

a=0.443 b=0.896 c=-0.896 d=0.443 e=589.739 f=-373.223

Ahora, si tenemos la siguiente coordenada de ejemplo: x=27, y=-9 , podemos transformarla, usando la matriz de transformación definida anteriormente como esta:

x'' = a*x + c*y + e x'' = 0.443*27 + -0.896*-9 + 589.739 x'' = 609.764 y'' = b*x + d*y + f y'' = 0.896*27 + 0.443*-9 -373.223 y'' = −353.018

Limpio, ¿eh? Puede obtener más información here

Pero eso no es todo. También necesitamos entender los datos de la ruta svg.
De acuerdo con la especificación de la ruta de svg svg, cada letra en los datos de ruta representa una instrucción. Y cada uno de los pares de números que siguen una instrucción representa un valor de coordenadas.

De su ejemplo, tenemos la siguiente ruta:

<path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" />

Aquí vemos que este objeto de ruta usa una instrucción de moveto absoluta ( M mayúscula), una curva smooth curveto relativa a smooth curveto de Bézier cúbica ( s minúscula), una instrucción de lineto relativa a ( l minúscula) y otra curva smooth curveto relativa a instrucción de curva Bézier cúbica, seguido de una instrucción closepath ( z minúscula).

M486,313 se traduce a M486,313 absoluto x = 486, y = 313
s27-9,43-29 es un poco más complicado de leer porque algunos comas se omiten porque no son necesarios si el número negativo es negativo, por lo que el signo menos actúa como coma; de todos modos, se traduce en una curva de bezier relativamente suave x = 27, y = -9, x = 43, y = -29 (un punto de destino y un punto de control)
Y así.

Entonces, ¿cómo aplicamos y eliminamos la matriz de transformación de su grupo svg? Al igual que:

// we read the transformation matrix params // <g transform="matrix(0.443,0.896,-0.896,0.443,589.739,-373.223)"> a=0.443 b=0.896 c=-0.896 d=0.443 e=589.739 f=-373.223 // we read the path data, and transform each instruction // <path d="M486,313s27-9,43-29l26,4,1,23-22,5s-25-6-48-3z" />

M486,313 Movimiento absoluto a

x'' = a*x + c*y + e = a*486 + c*313 + e = 524.589 y'' = b*x + d*y + f = b*486 + d*313 + f = 200.892

Mover a la instrucción ahora es M524.589,200.892

S27-9,43-29 - curva suave, repita el mismo proceso para cada coordenada, pero establezca e y f (parámetros de traducción) en 0, ya que es una instrucción relativa no absoluta.
Esto es ahora
s20.025,20.205,45.033,25.680999999999997

l26,4,1,23-22,5
se convertirá
l7.934000000000001,25.067999999999998, -20.165,11.085, -14.226, -17.497

s-25-6-48-3
se convertirá
s-5.698999999999999, -25.058000000000003, -18.576, -44.337

Y z permanecerá z

Entonces la ruta transformada resultante será:

<path d="M524.589,200.892s20.025,20.205,45.033,25.680999999999997l7.934000000000001,25.067999999999998,-20.165,11.085,-14.226,-17.497s-5.698999999999999,-25.058000000000003,-18.576,-44.337z" />

Espero que esto tenga sentido para ti.


¡Gracias ArtBIT por toda la información! Tuve algunos problemas al respecto en una aplicación de PHP, y escribí una biblioteca que manipula datos de fuentes (desde un archivo SVG) y realiza algún tipo de transformación en él. Cualquier persona interesada puede probarlo desde GitHub:

https://github.com/kartsims/easysvg

Ejemplo de uso:

require ''easySVG.php''; $svg = new EasySVG(); $svg->setFont("paris-bold-webfont.svg", 100, "#000000"); $svg->addText("Simple text display"); $svg->addAttribute("width", "800px"); $svg->addAttribute("height", "100px"); echo $svg->asXML();

Ejemplo de manipulación de datos SVG:

$def = ''YOUR SVG DEFINITION HERE''; $easySVG = new EasySVG(); // rotate by 40° $rotated_def = $easySVG->defRotate($def, 40) // rotate by 40° with center at (200,100) $rotated_def2 = $easySVG->defRotate($def, 40, 200, 100) // scale transform : width*4 $scaled_def = $easySVG->defScale($def, 4)


Puede hornear las coordenadas seleccionando la ruta y luego usando Ruta -> Unión (CTRL ++). Espero que esto ayude


Siguiendo la respuesta de @andraaspar, también puedes intentar desagrupar (Ctrl-U) y agrupar de nuevo (Ctrl-G). Funcionó para mí


Pegar en el lugar puede ayudarlo a:

  1. Haga doble clic en el grupo en Inkscape, para ingresarlo.
  2. Seleccione todos los contenidos del grupo presionando Ctrl + A, y cópielos con Ctrl + C.
  3. Haga doble clic fuera del grupo para salir del grupo.
  4. Edición> Pegar en el lugar (Ctrl + Alt + V) - en este punto, las transformaciones grupales se aplican a los objetos que se pegan.
  5. Agrupe los objetos nuevamente (Ctrl + G)
  6. Mueva el nuevo grupo a la misma profundidad que el original y elimine el grupo original . (Esto es probablemente más fácil con el editor XML, Ctrl + Shift + X).