En este artículo quiero resaltar las complejidades de trabajar con gráficos SVG, animación SVG (incluida la ruta), problemas y métodos para resolverlos, así como varias dificultades, de las cuales hay muchos SVG. Posiciono este artículo como una guía detallada.

No habrá complementos, bibliotecas, etc., solo hablaremos de SVG puro.
La única herramienta que usaré es Adobe Illustrator.
Prólogo
Todo comenzó con una conferencia aburrida y con la esperanza de entretenerme con al menos algo, decidí estudiar gráficos SVG, a saber, animación. Para mi sorpresa, había muy poca información en Internet. En todas partes había información duplicada que explicaba los conceptos básicos, pero sobre la animación en general a partir de la fuerza de 2-3 enlaces con información absolutamente idéntica, que es una traducción del artículo Una guía de animaciones SVG (SMIL) de Sarah Suydan.
Su artículo habla de todo, pero superficialmente. Sin embargo, le recomiendo que se familiarice con él. * Enlace a la traducción *Las siguientes semanas pasé recolectando información pieza por pieza de varias fuentes. El resultado de estas búsquedas es este artículo.
Exportación SVG adecuada desde Illustrator
Esta sección se centra en las características y los problemas de Adobe Illustrator, por lo que si no está utilizando Illustrator, puede omitir esta parte.
La preparación de un documento para la animación es una etapa muy importante, cuyo descuido puede tener consecuencias muy desagradables. Para enseñarle a dibujar mejor en Illustrator, no lo haré. Lo único que diré es que al dibujar formas, debe seguir los valores, es deseable que tengan solo un número después del punto decimal, y es mejor ser entero. Seguir esta regla no es necesario, pero reducirá el tamaño del archivo, simplificará más la animación y reducirá visualmente la cantidad de información. Echa un vistazo
<path d="M 17.7 29 C 28.2 12.9 47 5.6 62.8 10.4 c 28.2 8.5 30 50.5 24.8 53.1 c -2.6 1.3 -10.4 -6.1 -29.2 -34.6"/> <path d="M 17.651 28.956 c 10.56 -16.04 29.351 -23.359 45.12 -18.589 c 28.151 8.516 29.957 50.5 24.841 53.063 c -2.631 1.318 -10.381 -6.148 -29.235 -34.643"/>
En el ejemplo, la misma curva, pero en el primer caso, un dígito después del punto decimal, y en el segundo tres. Esta curva tiene solo 4 puntos, y el segundo ejemplo es un tercio más largo que el primero. Imagine cuánto espacio ocupará una curva de 20 puntos.
Después de que se dibuja la estructura alámbrica, debe guardar la imagen como un archivo SVG. Hay dos formas de hacerlo: Guardar como o Exportar como. ¿Pero qué camino elegir? Si confías en mí, mejor usa "guardar como". Si quieres saber por qué, entonces despliega un spoiler.
¿Entonces por qué?A primera vista, no hay diferencia, porque al final obtenemos un archivo .svg con nuestra imagen. Sin embargo, las diferencias comienzan en la etapa de configuración de exportación.
No veo ningún punto en explicar todos los parámetros en detalle, Illustrator lo hace muy bien en la sección "Descripción".Como puede ver, "guardar" tiene más configuraciones que "exportar", y para algunos será una buena razón para negarse a exportar, pero continuaremos.
Si abrimos archivos guardados en ambos sentidos en un navegador, no notaremos la diferencia. Sin embargo, en este momento estamos más interesados no en la apariencia, sino en el relleno, por lo que haremos lo mismo, sino a través de un editor de texto. Aquí las diferencias se harán más evidentes. Sugiero que usted mismo mire y saque conclusiones, no cambié nada en los archivos, simplemente copié todo como está.
Exportar <svg id="_1" data-name=" 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 51 51"> <defs> <style> .cls-1 { fill: none; stroke: #4ec931; stroke-miterlimit: 10; } .cls-2 { fill: #4ec931; } .cls-3 { fill: #fff; } </style> </defs> <title>my_icon_E</title> <circle class="cls-1" cx="25.5" cy="25.5" r="20"/> <circle class="cls-1" cx="25.5" cy="25.5" r="25"/> <g id="_2" data-name=" 2"> <circle class="cls-2" cx="25.5" cy="25.5" r="15"/> <polygon class="cls-3" points="25.5 34.8 34 20.3 17 20.3 25.5 34.8"/> </g> </svg>
Guardar <?xml version="1.0" encoding="utf-8"?> <svg version="1.1" id="_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve"> <style type="text/css"> .st0{fill:none;stroke:#4EC931;stroke-miterlimit:10;} .st1{fill:#4EC931;} .st2{fill:#FFFFFF;} </style> <circle class="st0" cx="50" cy="50" r="20"/> <circle class="st0" cx="50" cy="50" r="25"/> <g id="_2"> <circle class="st1" cx="50" cy="50" r="15"/> <polygon class="st2" points="50,59.3 58.5,44.8 41.5,44.8 "/> </g> </svg>
Además de las diferencias en nombrar clases de CSS y diseño en general, que algunos podrían considerar de buen gusto, hay otros problemas. Al "exportar", la imagen completa se redujo 2 veces. Puede juzgar esto por el tamaño de las formas y el atributo
viewBox . Como se trata de gráficos vectoriales, no empeoró, pero sigue siendo desagradable. "Guardar" dejó las dimensiones que especifiqué en Illustrator.
Pero todas estas son flores en comparación con el tipo de cerdo que puede "exportar". Específicamente, estos ejemplos no tienen este problema, probablemente porque la imagen es muy simple. Sin embargo, me encontré con él al exportar mi otro trabajo. Aquí está su captura de pantalla

El tamaño del archivo es lo suficientemente grande, por lo que solo daré la parte problemática
<g id="-21" data-name=""> <path class="cls-9" d="M477.94,456.75a1.83,1.83,0,0,1-.9,1.36l-4.91,3.1a7.29,7.29,0,0,1-7.5,0l-16.29-9.72a1.85,1.85,0,0,1-.92-1.56v-3.68a1.85,1.85,0,0,0,.92,1.56l.38.23,15.91,9.49a7.29,7.29,0,0,0,7.5,0l4.53-2.86.38-.23a1.87,1.87,0,0,0,.9-1.36Z" transform="translate(-5.5 -5.5)"/> <path class="cls-10" d="M477,451.19l-16.38-9.5a7.28,7.28,0,0,0-7.32,0l-5,2.9a1.88,1.88,0,0,0-.94,1.51v.17a1.85,1.85,0,0,0,.92,1.56l.38.23,15.91,9.49a7.29,7.29,0,0,0,7.5,0l4.53-2.86.38-.23a1.87,1.87,0,0,0,.9-1.36v-.51A1.88,1.88,0,0,0,477,451.19Z" transform="translate(-5.5 -5.5)"/> </g> <g id="-22" data-name=""> <path class="cls-9" d="M525.37,557.86a1.85,1.85,0,0,1-.9,1.36l-33.22,19.64a7.29,7.29,0,0,1-7.5,0l-16.29-9.72a1.85,1.85,0,0,1-.92-1.56v-3.68a1.85,1.85,0,0,0,.92,1.56l.38.23,15.91,9.49a7.29,7.29,0,0,0,7.5,0l32.84-19.41.38-.23a1.83,1.83,0,0,0,.9-1.36Z" transform="translate(-5.5 -5.5)"/> <path class="cls-10" d="M524.45,552.3l-16.38-9.51a7.31,7.31,0,0,0-7.32,0l-33.27,19.44a1.89,1.89,0,0,0-.94,1.51v.17a1.85,1.85,0,0,0,.92,1.56l.38.23,15.91,9.49a7.29,7.29,0,0,0,7.5,0l32.84-19.41.38-.23a1.83,1.83,0,0,0,.9-1.36v-.5A1.86,1.86,0,0,0,524.45,552.3Z" transform="translate(-5.5 -5.5)"/> </g>
¿Notó algo inusual? Si observa con recelo el atributo
transform , tiene razón. Es él quien estropea toda la frambuesa. Cuando "exporta" una imagen, Illustrator la asigna a TODOS los elementos
<path> . Sin embargo, tal problema no se observa con la "conservación".
Si todavía no comprende mi indignación, le explicaré: si desea animar el movimiento de dicho elemento, se desplazará hacia un lado. En este caso, 5.5 en ambos ejes. Esto se debe al hecho de que la animación de movimiento cambia el atributo de
transformación , restableciendo todos los valores pasados. Por supuesto, esto puede evitarse, pero no es mejor evitar el problema que corregir sus consecuencias más tarde ...
Por el momento, solo noté este problema, pero esto no significa que sea el único. Si evalúa la situación con sensatez, resulta que "guardar como" gana en todo. Por eso te aconsejo que lo uses.
Formas de importar un documento SVG en HTML
Antes de comenzar directamente con la animación, quiero hablar sobre cómo incrustar SVG en una página. Cada método tiene sus propias "características" que tienen un impacto directo en la animación. Y si no habla de ellos, entonces el artículo estará incompleto.
Suponga que ya tiene un SVG listo para usar con animación interactiva y que queda por incrustar este documento en el sitio. Como hacer esto
La opción número uno es recordar que SVG también es una imagen y se puede importar utilizando herramientas HTML estándar. Puede crear una
etiqueta <img> con un enlace a un documento
<img src="Hello_SVG.svg" />
O establecer SVG como imagen de fondo
#box { background-image: url("Hello_again.svg"); }
La principal desventaja de este método es el aislamiento de la imagen. SVG como una exhibición en el museo: se puede ver sin tocar. La animación en el interior funcionará, pero no se puede hablar de ninguna interactividad. Si, por ejemplo, un usuario hace clic en una animación, o si es necesario cambiar dinámicamente el contenido de un documento SVG, entonces este método no es para usted.
La opción número dos es crear un objeto desde SVG usando las etiquetas
<objeto> o
<embed> . También es posible usar
<iframe> para crear un marco, pero no recomiendo usar este método, porque se requiere una
muleta para todos los navegadores para que esta opción se muestre correctamente
<object data="My_SVG.svg" type="image/svg+xml"></object> <embed src="My_SVG.svg" type="image/svg+xml" /> <iframe src="My_SVG.svg"></iframe>
Aquí las cosas están mejor. Las animaciones tienen la oportunidad de ser interactivas, pero solo si se declaran dentro de un documento SVG y el contenido está disponible para JavaScript externo. Aún así,
<object> y
<iframe> pueden mostrar un trozo si de repente la imagen no se carga.
La opción número tres es simplemente pegar el contenido del documento SVG directamente en el HTML. Si puedes. El soporte SVG apareció en
el estándar HTML5 . Dado que SVG es esencialmente parte de la página en sí, el acceso a él está en todas partes. Las animaciones y los estilos de elementos pueden declararse tanto dentro del SVG como en archivos externos. La desventaja es que tales imágenes simplemente no se almacenan en caché por separado de la página
<body> ... <svg> </svg> </body>
Animación SVG
Hay dos formas principales de animar un elemento SVG:
- Animación CSS
- Animación SMIL integrada en SVG (de hecho, es una animación SVG que se basa en SMIL y extiende su funcionalidad)
Personalmente, los separo como animaciones de "externo" e "interno". Esta división es condicional, pero aún tienen diferencias funcionales. Si hablamos de las diferencias en general: CSS - tiene mejor soporte para navegadores; SMIL: tiene una gran funcionalidad. Es difícil decir cuál es mejor usar porque son muy parecidos La elección depende de la tarea, así que solo diré las razones principales para usar SMIL en lugar de CSS
SONRISA - cuando sea necesario:
- Lo que CSS no pudo hacer (animar un atributo no compatible, etc.)
- Tener un control más preciso sobre la animación.
- Hacer la transformación de ruta (animación del atributo d en la etiqueta de ruta )
- Sincronizar animaciones
- Haz animaciones interactivas
Si escribí que SMIL debería usarse para animaciones interactivas, esto no significa que no se pueda hacer lo mismo con CSS. Simplemente SMIL es una herramienta más funcional y sofisticada. Y es por eso que debe usarse solo cuando sea necesario. Si la animación es simple y se puede prescindir de CSS, entonces esto debería hacerse.
Animación CSS
Nada nuevo aquí. Podemos animar cualquier elemento SVG de la misma manera que lo hacemos con HTML. Todas las animaciones se crean usando
@keyframes . Dado que la animación CSS es otro tema, no me detendré en este punto en detalle, la red está llena de documentación y guías sobre este tema. Todo lo descrito allí se aplica a SVG, pero solo daré algunos ejemplos.
El documento SVG tiene hojas de estilo internas, por lo que escribiremos animaciones en ellas
<svg> <style> </style> </svg>
Animar un atributo SVG es tan simple como los atributos CSS
@keyframes reduce_radius { from { r: 10; } to { r: 3; } } @keyframes change_fill { 0% { fill: #49549E; } 75% { fill: #1bceb1; } 100% { fill: #1bce4f; } }
Puede especificar valores como un porcentaje y construir de-aEntonces solo queda aplicar las animaciones creadas al elemento deseado
.circle { animation: change_fill 1s, popup 2s; }
Todo lo que describí anteriormente es animaciones estáticas, no hay olor a interactividad allí. Pero, ¿y si realmente quieres? Bueno, todavía se puede hacer algo de forma interactiva y en CSS. Por ejemplo, si usa la
transición en combinación con la pseudo
clase hover .circle { fill: #49549E; transition: .3s; } .circle:hover { fill: #1bceb1; }
Cuando pasa el cursor sobre un elemento, cambiará su color de azul a azul durante 300 ms.Animación de atributos y una pequeña pieza de interactividad: aquí es donde terminan las características de la animación CSS. Pero esta funcionalidad es suficiente, porque la mayoría de las tareas se reducen a animar algún atributo. Casi cualquier atributo SVG puede ser animado. Y cuando escribo "casi cualquiera" quiero decir que si eliges un atributo aleatorio y resulta que no es invariante, entonces eres MUY afortunado.
Animación SMIL
Vale la pena decir de inmediato que la animación SMIL es tan antigua como el mundo y está desapareciendo, el soporte del navegador es decente, pero aún menos que la animación CSS, pero hay una razón por la cual SMIL sigue siendo atractivo: puede porque CSS no puede.
Hablaré más sobre SMIL, porque hay muchas trampas sobre las que rara vez escriben. Y este tema es menos popular que CSS. Las etiquetas principales para la animación son
<animate> ,
<set> ,
<animateTransform> ,
<animateMotion> .
<animado>
Comencemos con la artillería pesada.
<animate> : se utiliza para animar cualquier atributo y es la herramienta principal. Las etiquetas restantes son altamente especializadas, pero lo primero es lo primero.
¿Cómo aplicar animación a un elemento?Hay dos formas de especificar el elemento al que se aplicará la animación.
- Pon la etiqueta dentro del elemento. Este método le permite encapsular la animación dentro del objeto, lo que facilita la lectura del código.
<circle ...> <animate .../> </circle>
En este caso, la animación se aplicará al elemento del círculo . - Pase el enlace al artículo. Útil si desea que todas las animaciones se recopilen en un solo lugar
<svg xmlns:xlink="http://www.w3.org/1999/xlink"> <circle id="blue" .../> ... <animate xlink:href="#blue" .../> </svg>
Aquí se usa el atributo xlink: href , en el que especificamos la identificación del elemento al que debe aplicarse la animación. Para que este método funcione, debe definir el espacio de nombres xlink . Esto se hace en la etiqueta <svg>.
Con SVG 2, el atributo
xlink: href está en desuso, la especificación recomienda usar
href en su lugar, que no requiere un espacio de nombres
xlink .
<circle id="blue" .../> ... <animate href="#blue" .../>
Pero aquí, no todo es tan sencillo: Safari no admite
href . Resulta una situación de estancamiento, un atributo está desactualizado, el otro no está soportado parcialmente. Entonces, qué método usar, cada uno decide por sí mismo.
Para aquellos que han notado similitudes con los selectores de CSS: lamento decepcionarlos, no podré acceder a los elementos por clase
<circle class="blue_circle" .../> <animate href=".blue_circle" .../>
¡Esto no funciona!¿Cómo especificar un atributo para la animación?Hay
attributeName para esto. El valor es el nombre del atributo que animaremos.
<circle r="25" ...> <animate attributeName="r" ... /> </circle>
Al especificar r en attributeName , informamos que vamos a animar el radio del círculo¿Qué es attributeType y por qué no lo necesitas?Porque es inútilEn teoría, puede surgir un momento cuando los nombres de los atributos en CSS y XML coinciden, lo que puede generar problemas. Y para resolver este conflicto, debe especificar explícitamente un espacio de nombres. Hay dos
sillas de dirección : especifique un prefijo o use
attributeType . Comencemos con el prefijo.
En todas partes escriben algo como lo siguiente:
Puede especificar un prefijo XMLNS para un atributo para especificar explícitamente su espacio de nombres
Este método se menciona de pasada y sin ejemplos. Entonces no cambiaré las tradiciones. (Te aconsejo que pares aquí, te olvides de los prefijos como una pesadilla y vayas a
attributeType , te lo advertí)
"Soy un masoquista"El contenido de este spoiler es bastante entretenido y de naturaleza exploratoria. No hay información útil, aparte del hecho de que los prefijos no funcionan, no lo encontrará aquí.Primero, necesita encontrar una definición más precisa y, como sabe, las definiciones más precisas en las especificaciones y estándares.
La traducción de la definición dice lo siguiente:
"Define el nombre del atributo de destino. El prefijo XMLNS se puede usar para especificar el espacio de nombres XML para un atributo. El prefijo se interpretará en el ámbito del elemento de animación ".
Hmm, no fue más fácil. ¿Qué le viene a la mente a una persona que no conoce XML después de leer tal definición? Derecho Lo mismo que yo
Lo tomé literalmente y pensé que debería verse así
<animate attributeName="xmlns:* *"/>
Pensé y me olvidé de este método antes de escribir este artículo. Los problemas comenzaron cuando decidí probarlo en la práctica. Creo que no sorprenderé a nadie si digo que esto no funciona. Después de varias horas de búsquedas infructuosas, busqué en Google "prefijo xmlns" y, para mi sorpresa, vi que xmlns no es el prefijo en sí, sino
(concéntrese, será difícil ahora) el diseño del espacio de nombres con prefijos .
Se ve de la siguiente manera:
<** xmlns:**="* url *" ...>
Entonces me di cuenta de que no entendía nada ... al principio ... y ahora, en principio, tambiénDespués de un par de horas más, finalmente encontré lo que estaba buscando en
espacios de nombres en XML . Aquí hay un ejemplo original:
<x xmlns:n1="http://www.w3.org" xmlns="http://www.w3.org" > <good a="1" n1:a="2" /> </x>
¿Pero sabes qué es lo más divertido? Aún no funciona. Aunque todo se hace de acuerdo al libro.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:n1="http://www.w3.org/2000/svg"> <circle id="www" n1:r="10" .../> <animate href="#www" attributeName="n1:r" .../> </svg>
No hay errores y no debería serlo, porque todo se hace de acuerdo con las reglas, pero el problema es que obtenemos un círculo sin radio. El mismo resultado será si simplemente no escribe el atributo
r .
Epílogo : SVG ignora los atributos prefijados. Como resultado, incluso si SMIL realmente anima el atributo con un prefijo, no verá el resultado de esta animación.
En mi defensa, diré que solo traté con SVG, es decir, con su animación, por lo que el gurú XML dejaría de lado las antorchas y la horca. Si sabe cómo hacer que este método funcione, bienvenido comentarios Para indicar explícitamente a qué pertenece el atributo animado, se utiliza attributeType. Se necesitan 3 valores:
CSS ,
XML ,
automático . A menos que
attributeType se especifique explícitamente, se utilizará
auto . En este caso, las propiedades CSS se verifican primero, y si no hay coincidencias, se verifican los atributos del elemento objetivo. En el ejemplo, indicamos que vamos a animar exactamente la propiedad CSS
<animate attributeType="CSS" attributeName="opacity" .../>
Bueno,
attributeType le permite fácilmente y sin muletas indicar a qué pertenece el atributo animado, resolviendo así el "problema", que ni siquiera existe.
Inesperadamente, ¿verdad? Como dije al comienzo del capítulo: SMIL está muriendo y esto se debe al hecho de que la animación se transfiere a los rieles de CSS. La mayoría de los atributos duplicados son absolutamente idénticos entre sí, es decir no importa si pertenece el atributo CSS o SMIL; el resultado será el mismo. Y en combinación con el valor
automático predeterminado, ya no es necesaria la definición explícita de
attributeType .
Un momento de hechos interesantes: attributeType no es compatible con SVG. ¿De dónde vino entonces? Él vino a nosotros desde SMIL Animation, en el que se basa la animación SVG. Y también attributeType se elimina después de SVG 1.1 Segunda edición. Todas las pruebas aquí¿Cómo determinar los valores de animación?No basta con especificar un atributo para la animación; debe definir sus valores. Aquí vienen
de ,
a ,
por ,
valores .
Comencemos con una pareja que siempre está junta:
de y
para . El significado de su existencia es obvio,
desde el principio
hasta el final.
<circle r="25" ...> <animate attributeName="r" from="10" to="45" .../> </circle>
El resultado de la animación será un cambio suave en el radio del círculo de 10 a 45Aunque dije que siempre están juntos,
to también se puede usar sin declarar explícitamente. En este caso,
from tomará el valor definido en el elemento de destino. Para el ejemplo anterior, la animación comenzará a las 25.
Si es necesario especificar un conjunto de varios valores, se utilizan valores. Los valores se enumeran con un punto y coma.
<circle r="25" ...> <animate attributeName="r" values="15;50;25" .../> </circle>
El valor del radio disminuye a 15, luego aumenta a 50 y luego vuelve a su posición original.Último en línea
por . No le importa "dónde" y "dónde", todo lo que le interesa es "cuánto". En otras palabras, en lugar de valores absolutos, funciona con relativa
<circle r="25" ...> <animate attributeName="r" by="15" .../> </circle>
Como resultado de la animación, el radio aumentará en 15, es decir, obtendrá 25 + 15 = 40Una leyenda recorre las extensiones de manuales que
" por pueden usarse para indicar la cantidad en que las animaciones deberían avanzar" . Lo entiendo de esta manera: si
de = 20 ,
a = 50 , y dado
por = 10 , entonces este camino debe superarse "saltando" en 10, es decir 20, 30, 40, 50. Pero no importa cómo lo intenté, con y sin, la animación no cambió un poco. Además, no encontré confirmación en la especificación. Parece que es solo un error.
Los valores tienen la máxima prioridad, luego
de -
a , último
por . La prioridad más baja explica
por qué una "leyenda" no puede funcionar en principio. Sin embargo,
by funciona junto con
from , en este caso,
from simplemente anula la posición actual del elemento
<circle cy="50" ...> <animate attributeName="cy" from="70" by="30" .../> </circle>
Aquí la animación en lugar de 50 comienza en 70 y termina en 100Más sobre animaciones relativasPuede hacer que otros atributos funcionen igual que
by . Esto se hace usando el atributo
aditivo , que tiene dos posiciones:
reemplazar y
sumar .
El primero es el predeterminado, por lo que estamos interesados en el segundo. Con un valor de suma, todos los atributos se agregarán al valor actual del elemento de destino, es decir. Al animar un radio de 20 con los valores form = 5 y to = 15 , la animación será de 20 + 5 a 20 + 15 <circle r="20" ...> <animate attributeName="r" from="5" to="15" additive="sum" .../> </circle>
Al realizar la animación, habrá un salto brusco a la posición 25, lo que no es bueno (a menos que, por supuesto, esto sea lo que se pretende). Esto se puede evitar con la forma = 0 , pero entonces en contra del propósito de la utilización de suma , ya que el mismo efecto se puede obtener sin aditivo uso por <animate attributeName="r" from="0" to="15" additive="sum" .../> <animate attributeName="r" by="15" .../>
En cuanto a mí, el segundo método es mucho más comprensible y conveniente.¿Dónde especificar la duración de la animación?El último atributo requerido se deja para hacer una animación de trabajo, y esto es durante . El valor del atributo determina la duración de la animación, que puede especificarse tanto en segundos como en milisegundos. <animate dur="0.5s" .../> <animate dur="500ms" .../> <animate dur="00:00:00.5" .../>
Desde la última línea puedes adivinar que hay algo más ...También puedes indicar los valores en minutos e incluso horas <animate dur="1.2min" .../> <animate dur="0.02h" .../>
Joder sabe, ¿por qué demonios lograste indicar los valores en horas, pero no me meto en los asuntos de otras personas, si quieres, significa por qué ...Para otros atributos, los valores temporales se establecen en las mismas formas¿Qué puedo hacer para evitar que la animación regrese al principio?El atributo de relleno (no confunda este atributo con su homónimo) es responsable del comportamiento del elemento después del final de la animación. Hay dos opciones:- eliminar (valor predeterminado): tan pronto como la animación llega a su fin, todas las transformaciones se restablecen y el elemento toma un estado como antes de la animación
- congelar : el elemento se congela en la posición final de la animación
¿Es posible hacer un bucle de animación?La respuesta es si. Para hacer esto, el atributo repeatCount especifica un valor indefinido . El atributo determina el número de repeticiones de la animación y el valor predeterminado es 1, pero puede especificar cualquier número <animate repeatCount="indefinite" .../> <animate repeatCount="3" .../>
El primero se repetirá sin cesar, el segundo funcionará 3 veces.Ahora las animaciones interminables me molestan, ¿puedo apagarlas después de un tiempo?Para gente tan molesta repitió Dur . ¡Este atributo detiene la animación después de un cierto tiempo desde el comienzo de la animación! En pocas palabras, repetirDur limita la duración de la animación. La principal diferencia de repeatCount es que la animación se puede detener en el medio <animate dur="2s" repeatCount="indefinite" repeatDur="3s" .../>
La animación se interrumpirá en la mitad de la segunda iteración.¿Y si quiero que la animación no comience de inmediato?Entonces, amigo mío, se proporciona el atributo de inicio . Él es responsable de cuándo comienza la animación. Este atributo es muy útil porque también se usa para sincronizar varias animaciones, pero más sobre eso más adelante.Si necesita especificar el retraso habitual en el lanzamiento, entonces escribimos a través de qué período de tiempo debe comenzar la animación después de abrir el documento <animate begin="1.5s" .../>
La reproducción comienza después de 1,5 segundos.También puede especificar un valor negativo. Entonces la animación comenzará no desde el principio, sino en el lugar donde sería después de un período de tiempo específico <animate begin="-2s" dur="4s" .../>
,begin , , «on». , , «onclick»
click <circle ...> <animate begin="click" .../> </circle>
, . ,
id <circle id="button" .../> ... <animate begin="button.click" .../>
.
<animate begin="click; 0s" .../>
La animación comenzará cuando se cargue el documento y al hacer clic. No todos los eventos son compatibles, pero la mayoría de los eventos relacionados con el mouse funcionan. No los enumeraré a todos, los eventos disponibles se pueden encontrar en algún lugar aquí . Además, nadie ha cancelado el método de búsqueda científica.La animación se reinicia sin llegar al final, ¿cómo puedo solucionarlo?Daré un ejemplo simple. Aquí la animación comienza haciendo clic. Si el usuario aún no presiona, el inicio automático se proporciona en 3 segundos. <animate begin="click; 3s" dur="7s" .../>
Pero hay un problema: si el usuario presiona antes del temporizador automático, cuando transcurran 3 segundos, la animación se reiniciará y nunca llegará al final. El atributo de reinicio en el valor whenNotActive vendrá al rescate . En total, tiene tres de ellos.- siempre es el valor predeterminado: le permite reiniciar la animación en cualquier momento
- whenNotActive : la animación se puede iniciar si aún no se está reproduciendo
- nunca : prohíbe reiniciar la animación
<animate begin="click; 3s" dur="7s" restart="whenNotActive" .../>
El problema está resuelto, aunque en la mayoría de los casos puede prescindir de este atributo simplemente construyendo dependencias de manera competenteSincronización de animacionesAdemás de los eventos estándar, por tipo de clic, hay eventos de inicio, finalización y repetición de la animación. Para vincular un evento, debe especificar la identificación de la animación y, a través del punto, comenzar , finalizar , repetir, respectivamente <animate id="pop" begin="click" .../> <animate begin="pop.begin" .../> <animate begin="pop.end" .../>
Si con los dos primeros todo está claro, con la repetición no todo es tan obvio. El número de repeticiones se escribe entre paréntesis, después de lo cual debe comenzar la animación (este número no puede ser la última repetición) <animate id="flip" repeatCount="5" .../> <animate begin="flip.repeat(2)" .../>
La animación comenzará después de dos repeticiones, y no cada 2 repeticiones. También puede especificar un retraso en relación con el evento. Por ejemplo, si quiero reproducir la animación 2 segundos después del inicio de otra <animate id="another" .../> <animate begin="another.begin + 2s" .../>
O comience la animación un segundo antes del final de otra <animate begin="another.end - 1s" .../>
¿Qué más puede comenzar?Quería llamar a esta sección, pero es más correcto llamarla "¿Qué debería ser capaz, pero no capaz?". Según mi especificación favorita , begin debería tener dos valores más que debería tomar. El primero es accessKey , que inicia la animación presionando una tecla especificada en formato Unicode. El segundo es wallclock , que determina el inicio de la animación en tiempo real. Y allí puede especificar no solo el reloj, sino incluso el mes y el año, en general, un conjunto completo.Lamentablemente, ninguno de ellos quería trabajar. Aunque la pérdida no es grande, porque la necesidad de ellos aún es dudosa <animate begin="accessKey(\u0077)" .../> <animate begin="wallclock(2019-04-09T19:56:00.0Z);" .../>
No sé cuál es el problema, tal vez mi navegador no los admite, o tal vez algo más ...¿Puedo interrumpir la animación?Esto se puede hacer con el atributo final . En su uso, es idéntico para comenzar , también puede especificar la hora, eventos, etc. Como puede ver, esta no es la primera (y no la última) forma de interrumpir la animación, porque hay repeatDur , donde también puede corregir la duración de la animación. Yaunque también puede especificar el tiempo directamenteal final , sus características distintivas son el enlace de eventos y la capacidad de especificar una lista de valores.Supongamos que tenemos un elemento que tiene un estado de descanso y actividad. El segundo se activa cuando se hace clic. Y queremos interrumpir el resto de la animación con el inicio de la actividad. Puedes implementar una idea similar como esta <animate id="idle" end="action.begin" begin="0s" repeatCount="indefinite" .../> <animate id="action" begin="click" .../>
El resto de la animación se inicia por defecto. Cuando hace clic en un elemento, una animación de actividad comienza e interrumpe la animación de descanso.Combinando los atributos end y beginComo ya sabe, ambos begin y end pueden tomar una lista de valores, pero aún no está claro cómo se comportará la animación si especifica una lista en ambos atributos. Y resultará, en cierto modo, una repetición con una duración configurable e intervalos entre ellos ... ¿no está claro? Explicaré todo ahora.Lo primero que debe saber es que el número de valores en las listas debe coincidir. Cada par de valores de inicio - findefine una "repetición". Y el tiempo entre el final de una "repetición" y el comienzo de la siguiente determina el retraso. Los llamo "repeticiones" por una razón, la animación no se detiene y continúa, sino que se interrumpe y comienza desde el principio. Resulta que podemos ajustar por separado la duración de cada repetición y establecer diferentes retrasos después de cada repetición <animate dur="3s" begin="1s; 5s; 9s" end = "2s; 8s; 11s" .../>
En el ejemplo, la animación tiene 3 "repeticiones". El primero comenzará un segundo después de cargar el documento y durará solo un segundo de cada tres. Luego un retraso de 3 segundos, y luego una animación completa de 3 segundos. De nuevo, un retraso, pero en 1 segundo. La última repetición se interrumpirá después de dos segundos de animación.¿Puedes interrumpir la animación de alguna manera?Un par de atributos inútiles para la alcancíaKeeneeee, hay dos atributos más: min y max . Como su nombre lo indica, min define el mínimo y max define laduración máxima. Primero, la duración de la animación se calcula utilizando los valores dur , repeatCount , repeatDur ,terminar . Y después de eso, la duración obtenida se ajusta a los cuadros especificados por min y max . Todo es hermoso en papel, veamos cómo funciona en la práctica.Con max, todo es simple, este es otro atributo que define el límite superior. Si la duración calculada es inferior al máximo , se ignora y, si es más larga, la duración de la animación es igual al máximo. <animate dur="10s" repeatDur="7s" end="5s" max="4s" .../>
Será interrumpido por 4 segundos,pero min fue menos afortunado. Si la duración calculada de la animación es mayor que min , entonces se ignora, lo cual es lógico. Sin embargo, si la duración calculada es menor que min , entonces ... a veces se ignora, y a veces no.¿Por qué por qué? Este momento es muy fácil de confundir, así que léalo detenidamente.Tenemos dos opciones cuando la duración calculada es menor que min :- Porque la animación en sí ha terminado, es decir dur * repeatCount < min
<animate dur="2s" repeatCount="2" min="5s" .../>
En esta opción, el atributo min simplemente se ignora, la animación se detendrá en el cuarto segundo - repeatDur end .
Debido a la abundancia de atributos que interrumpen la animación, hay mucha confusión. Como resultado, no tiene mucho sentido en max y min , porque la animación bien escrita elimina la necesidad de ellos.¿Cómo gestionar fotogramas clave y dónde indicar la función de tiempo?Para hacer esto, necesita conocer los atributos keyTimes , keySplines , calcMode . Habiendo especificado la lista en valores , declaramos cuadros clave, pero se distribuyen de manera uniforme. Gracias al atributo keyTimespodemos acelerar o ralentizar la transición de un estado a otro. En él, también en forma de lista, se indican los valores para cada cuadro. Los valores representan la posición del fotograma clave en el eje de tiempo como un porcentaje, en relación con la duración de toda la animación (0 - 0%; 0.5 - 50%; 1 - 100%).Hay varias reglas: cada valor representa un número de coma flotante de 0 a 1, el número de valores en las listas debe coincidir, el primer valor debe ser 0 y el último 1, cada valor siguiente debe ser mayor que el anterior. Creo que entiendes que no tiene sentido usar keyTimes sin valores . Y ahora un ejemplo <animate values="15; 10; 45; 55; 50" keyTimes="0; 0.1; 0.6; 0.9; 1" .../>
Por defecto, todas las conversiones ocurren linealmente, para cambiar esto, debe especificar un modo diferente en calcMode . Y no hay muchas opciones:- lineal - valor estándar, no se necesita explicación
- estimulado : los intervalos de tiempo se calculan de modo que la velocidad entre fotogramas clave sea constante
- discreto : la animación cambia entre fotogramas clave en saltos, sin interpolación
- spline : podemos decir que este es un modo de control manual (más adelante)
Desafortunadamente, estas son todas las funciones integradas, aquí no encontrará la facilidad de \ out como en CSS. Entonces, estas necesidades tendrán que satisfacer el régimen, al que llamé "manual".Lo más difícil de entender es el ritmo , por lo que lo explicaré con más detalle. Para comenzar, vea cómo funciona la animación en modo estándar. La animación dura 2 segundos y tenemos 3 fotogramas clave: inicial, intermedio, final <animate dur="2s" values="100; 200; 150" .../>
Si mira la animación, será obvio que el movimiento entre fotogramas clave se produce a intervalos regulares. La distancia entre el primero y el segundo es 100, y entre el segundo y el tercero es 50, es decir. La mitad del primer camino. No es difícil calcular que el elemento pasará por el segundo segmento dos veces más lento que el primero. Ahora agregue calcMode = "estimulado" y vea qué ha cambiado. <animate dur="2s" values="100; 200; 150" calcMode="paced" .../>
Y la velocidad del elemento ha cambiado. Ahora está diseñado para cubrir toda la distancia a la misma velocidad, en otras palabras, el elemento moverá ambos segmentos de manera uniforme.Ahora veamos el modo spline y el atributo keySplines . Tienen algunas similitudes ... hmm ...Si spline define un modo manual, el atributo keySplines define los valores para este modo. Obviamente, uno no funciona sin el otro. Los valores en keySplines se establecen mediante una lista donde se indican las coordenadas de dos puntos para Bezier cúbico.Más información sobre la función cúbica de Bezier, . 4 0 1 : cubic-bezier(x1, y1, x2, y2). , .

cubic-bezier .
, .
El número de valores en keySplines debe ser 1 menor que los valores . Esto se debe al hecho de que indicamos valores no para cuadros clave, sino para intervalos entre ellos. <animate values="100; 200; 150" keySplines=".25 .1 .25 1; 0 0 .58 1" calcMode="spline" .../>
,– , .
–
from -
to by , :
keyTimes "0; 1" <animate from="10" to="50" keyTimes="0; 1" keySplines=".25 .1 .25 1;" calcMode="spline" .../>
Si en lugar de from - para usar valores con dos valores, entonces no habrá tal problema¿Cómo implementar animaciones acumulativas?Primero, una pequeña teoría: la próxima repetición de la animación acumulativa continuará donde terminó la anterior. Sería genial, pero no muy ... El hecho de que las animaciones acumulativas funcionen solo dentro de la repetición es decepcionante.Ahora sobre cómo hacer que la animación sea acumulativa: debe configurar el atributo acumular (que no es ninguno de forma predeterminada) para sumar <animate by="100" repeatCount="3" accumulate="sum".../>
Debe tenerse en cuenta que si usa valores o de - a , todas las repeticiones, excepto la primera, se comportarán como si aditivas = "suma" . Y acumular se ignora si solo se especifica uno .Comprendemos la transformación del contornoAhora que he explicado los conceptos básicos, es hora de pasar a cosas realmente geniales y complejas. Estoy seguro de que alguien abrió este artículo únicamente por el bien de esta sección.La transformación de ruta es una animación del atributo d de la etiqueta de ruta , que le permite crear el efecto de cambiar suavemente la forma de la forma. Actualmente, con las herramientas integradas, esto solo se puede hacer con SMIL. Envalores indica la lista de valores para el atributo d a través del cual pasa el elemento. También puede usar de - a . En general, el esquema morph se ve así <animate attributeName="d" values=" 1; 2; ..." .../>
Y ahora pasemos a las complejidades de este proceso:para aquellos que están en el tanque, el atributo d contiene un conjunto de puntos que posteriormente se conectan para formar una figura. Una mirada más cercana revela que la lista de valores es similar al conjunto de instrucciones para la máquina CNC (o "robot" en las lecciones de informática). Hay muchos equipos, algunos son responsables de "mover el cursor", otros de "dibujar", algunos de cuánto será la curva de la línea, etc. ( Todos los equipos están aquí ).Para que la transformación funcione, el número de comandos debe coincidir y deben ser del mismo tipo . Si ignora esta condición, no habrá interpolación: la animación saltará de un estado a otro, como concalcMode = "discreto" . A primera vista, no es nada complicado, y esto es así si animas formas sin curvas. Si no, entonces comienzan las dificultades.Al crear gráficos complejos, todos usan editores vectoriales y tienen la costumbre de optimizar el "código" tanto como sea posible. Esto suele ser una ventaja, pero no en nuestro caso. A la salida, que puede ser una lista larga, pero con equipos de diferentes tipos, y es una violación de una de las reglas. Usé Adobe Illustrator y no encontré una opción que pudiera arreglar las cosas. A veces, por voluntad de los dioses del dizign, este problema está ausente. Pero en serio, la probabilidad de un problema es directamente proporcional a la complejidad de la figura y la transformación.Por el momento, la única solución al problema es la conversión del "código torcido" en la aplicación web Shape Shifter . Esta es la opción que uso. Además de arreglar el código roto, Shape Shifter le permite ver el resultado, opcionalmente agregar otro tipo de animación y exportar el resultado en un formato conveniente.El siguiente será un tutorial paso a paso donde te diré cómo hacer una animación tan hermosa
Enséñame: SVG Adobe Illustrator, , Shape Shifter . CSS, SMIL .
. Illustrator. , . 200x200 .
, , . , , «». ,
. . « »
, . , , ,
. , , . , . SVG , . …
. , . SVG . ( Illustrator )
, , Illustrator
<path> ,
<circle> . , . , , . - (
SVGO ), . .
d , ) <?xml version="1.0" encoding="utf-8"?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve"> <style type="text/css"> .st0{fill:#D38911;} .st1{fill:#87872B;} .st2{fill:#CEB629;} .st3{fill:none;stroke:#DD913E;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:12,200;} </style> <g id="Pulse"> <g> <path class="st0" d="M100,87c44.1,0,80,35.9,80,80s-35.9,80-80,80s-80-35.9-80-80S55.9,87,100,87 M100,82c-46.9,0-85,38.1-85,85 s38.1,85,85,85s85-38.1,85-85S146.9,82,100,82L100,82z"/> </g> </g> <g id="_x3F__1_"> <path id="side" class="st1" d=" "/> <path id="front" class="st2" d=" "/> </g> <g id="Particles"> <line class="st3" x1="80" y1="162.9" x2="42" y2="59.1"/> <line class="st3" x1="90.1" y1="148.8" x2="59.8" y2="28.8"/> <line class="st3" x1="107.9" y1="155.6" x2="124.9" y2="15.9"/> <line class="st3" x1="94.4" y1="160.4" x2="154.3" y2="7.2"/> <line class="st3" x1="119.3" y1="157" x2="159.2" y2="75.5"/> <line class="st3" x1="98" y1="169" x2="87.7" y2="10.7"/> <line class="st3" x1="80.4" y1="147.6" x2="63.2" y2="14.1"/> </g> </svg>
<?xml version="1.0" encoding="utf-8"?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"> <style type="text/css"> #Pulse{fill: none; stroke: #D38911; stroke-width: 5;} #side{fill:#87872B;} #front{fill:#CEB629;} .particles{fill:none;stroke:#DD913E;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:12,200;} </style> <circle id="Pulse" cx="100" cy="167" r="85"/> <g id="Sign"> <path id="side" d=" "/> <path id="front" d=" "/> </g> <g id="Particles"> <line class="particles" x1="80" y1="162.9" x2="42" y2="59.1"/> <line class="particles" x1="90.1" y1="148.8" x2="59.8" y2="28.8"/> <line class="particles" x1="107.9" y1="155.6" x2="124.9" y2="15.9"/> <line class="particles" x1="94.4" y1="160.4" x2="154.3" y2="7.2"/> <line class="particles" x1="119.3" y1="157" x2="159.2" y2="75.5"/> <line class="particles" x1="98" y1="169" x2="87.7" y2="10.7"/> <line class="particles" x1="80.4" y1="147.6" x2="63.2" y2="14.1"/> </g> </svg>
, . , ,CSS , . . , . . CSS . :
#Pulse{fill: none; stroke: #D38911; stroke-width: 5; transform: rotateX(80deg);} ._transformer{transform-box: fill-box; transform-origin: center;}
,
_transformer , , . «»
<animateTransform> .
- :
, Illustrator? …– , . , . ,
<path> , .
, ! – , . , – .
circle , .
animate , 3
<circle id="Pulse" class="_transformer" cx="100" cy="167" r="0"> <animate id="doPulse" attributeName="r" values="0;85;" dur=".8s" begin="Sign.click" calcMode="spline" keySplines="0,0,.58,1"/> <animate attributeName="stroke-width" values="5;12;" dur=".8s" begin="doPulse.begin"/> <animate attributeName="opacity" values="0.5;1;1;0" keyTimes="0;0.2;0.5;1" dur=".8s" begin="doPulse.begin"/> </circle>
, CSS, . : , , . - :
. - , . ,
<linearGradient id="light-gradient"> <stop offset="0%" stop-color="#ffffff00"/> <stop offset="10%" stop-color="#FFF"/> <stop offset="90%" stop-color="#FFF"/> <stop offset="100%" stop-color="#ffffff00"/> </linearGradient> <mask id="light-mask"> <rect y="0" x="90" class="_transformer" width="20" height="220" fill="url(#light-gradient)" /> </mask>
, . , , . ,
<use> ,
<path> <defs> <defs> <path id="question" d=" "/> </defs> ... <use id="front" href="#question"/> <use id="light" href="#question" mask="url(#light-mask)"/>
, , . . ,
#light-mask rect{ animation: highlight 4s infinite; } @keyframes highlight { 0% { transform: translate(-100px,0) rotate(-50deg); } 30% { transform: translate(100px,0) rotate(-50deg); } 100% { transform: translate(100px,0) rotate(-50deg); } }
. . CSS , SMIL.
, . — , . ,
<g id="Sign" class="_transformer"> <path id="side" d=" "/> <use id="front" href="#question"/> <use id="light" href="#question" mask="url(#light-mask)"/> <animateTransform id="idle" attributeName="transform" type="translate" values="0,0;0,-5;0,0" dur="6s" begin="0s; jump.end" end="click" repeatCount="indefinite" /> <animateTransform id="jump" attributeName="transform" type="translate" calMode="spline" values="0,0;0,10;0,-35;0,5;0,0" keyTimes="0;0.1;0.35;0.6;1" keySpline="0,0,.58,1;0,0,.58,1;.42,0,1,1;0,0,.58,1" dur="1s" begin="idle.end" /> </g>
,, , . ,
additive="sum" <animateTransform attributeName="transform" type="scale" additive="sum" values="1,1;1.1,0.8;0.9,1.2;1.1,0.8;1,1" keyTimes="0;0.1;0.35;0.7;1" dur="1s" begin="idle.end" />
, , . Resultado:
.
? - , , .
stroke-dashoffset , . ,
- . ,
<g id="Particles"> ... </g> <g id="Sign" class="_transformer"> ... </g>
, ,
.particles{ opacity:.7; stroke-width:0; ... }
, . ,
@keyframes sparks { 0% { stroke-dasharray: 20,200; stroke-width: 5px; } 100% { stroke-dasharray: 4,200; stroke-width: 0px; stroke-dashoffset: -180; } }
, . , , «». : CSS , , . SMIL, 3 , , 7. , , …
– , - , . CSS, SMIL.
Particles_active ,
.Particles_active .particles{ animation: sparks .7s; }
<set> , , (
set )
<g id="Particles"> <line class="particles" x1="80" y1="162.9" x2="42" y2="59.1"/> ... <line class="particles" x1="80.4" y1="147.6" x2="63.2" y2="14.1"/> <set attributeName="class" to="Particles_active" dur=".7s" begin="jump.begin + .5s"/> </g>
:. , , . 3D , . , , .
Adobe Illustrator, . , . - , . ,
d .
, . Shape Shifter.
, , . , Shape Shifter, SVG . Shape Shifter , «» SVG. Illustrator. , . , pathData
, , toValue. . «»
. ,
, , Shape Shifter , , , , . , toValue fromValue .
. ,
<animate attributeName="d" calMode="spline" values=" 1; 2; 1" dur="5s" keySpline=".42,0,.58,1;.42,0,.58,1" repeatCount="indefinite" />
1 – , 2 –. Codepen.
, SVG – , . , ,
<set>
La etiqueta set es una versión abreviada de animate , excepto que no puede interpolar. Se utiliza para cambiar instantáneamente el atributo durante un cierto período de tiempo, es decir. funciona según el principio de un interruptor. Como resultado, ignora los atributos asociados con la interpolación y no admite animaciones acumulativas o relativas. El valor se establece exclusivamente por el atributo que , atributos valores , a partir , por ignorado <set attributeName="cx" to="200" begin="click" dur="5s" .../>
El elemento cambia de posición haciendo clic, después de 5 segundos vuelve a su posición original.Si no especifica el atributo dur , el elemento permanecerá en este estado hasta que se vuelva a cargar el documento. De lo contrario, es similar a la animación .<animateTransform>
Como su nombre lo indica, se usa para aplicar diversas transformaciones a un elemento. Todos los tipos de transformaciones son idénticas a las transformaciones CSS. Con el uso simultáneo de las transformaciones CSS y SMIL, se anularán entre sí, por lo que es mejor usar una cosa o mirar para que no se superpongan.¿Cómo transformar?El atributo animado es transformar . El modo de transformación se indica en el atributo de tipo y toma 4 tipos de valores: movimiento, rotación, escala, desplazamiento a lo largo de los ejes.traducir : mover un elemento en relación con su posición actual. Toma un desplazamiento en el formato [x, y] , donde y es un parámetro opcional <animateTransform attributeName="transform" type="translate" from="0, -10" to="0, 10" .../>
Mueve el elemento a lo largo del eje Yrotar : gira el elemento en relación con el centro de rotación. Toma el ángulo de rotación y las coordenadas del centro de rotación [grados, x, y] como valores, las coordenadas del centro son opcionales. Por defecto, el centro de rotación está en la esquina superior izquierda del documento SVG <animateTransform attributeName="transform" type="rotate" from="0, 150, 150" to="45, 150, 150" .../>
Gire 45 grados alrededor de un punto con coordenadas 150, 150Además, el centro de rotación se puede cambiar utilizando la propiedad CSS de origen de transformación , donde además de las coordenadas, puede especificar porcentajes. De manera predeterminada, los porcentajes se calculan por el tamaño de todo el documento, por lo que los porcentajes se calculan en relación con el elemento, debe establecer la propiedad CSS del cuadro de transformación con el valor del cuadro de relleno .escalar : escala el elemento. Como valores, toma números de coma flotante en el formato [escala] para ambos ejes, o por separado para cada eje [escalaX, escalaY] (1 corresponde al tamaño normal del elemento). Si no cambia el cuadro de transformaciónComo mencioné anteriormente, el elemento se escala en relación con todo el documento. El espacio vacío alrededor del elemento también cambia con él, por lo que visualmente parece que el elemento se desplaza hacia un lado <animateTransform attributeName="transform" type="scale" from="1, 1" to="2, 1" .../>
Estira un elemento a lo largo del eje XskewX o skewY : desplaza un elemento en relación con el eje. El valor toma el ángulo de inclinación [deg] . Por defecto, el centro de desplazamiento es la esquina superior izquierda, por lo que el mismo chiste con transform-box y transform-origin funciona aquí comoen otras transformaciones. <animateTransform attributeName="transform" type="skewX" from="0" to="45" .../> <animateTransform attributeName="transform" type="skewY" from="90" to="0" .../>
Uno se desplaza a lo largo de X, otro a lo largo de YSuma y redefinición de transformacionesEn animateTransform , aún puede realizar animaciones acumulativas y relativas, sin embargo aquí el atributo aditivo se comporta de manera diferente. En el valor de replace, la transformación anula todas las anteriores. En el valor de suma , latransformación se suma con la anterior. <rect transform="skewY(115)" ...> <animateTransform type="translate" from="-10" to="10" additive="replace" .../> <animateTransform type="rotate" from="0" to="90" additive="sum" .../> </rect>
En este ejemplo, el desplazamiento del rectángulo se redefinirá para mover y rotar<animateMotion>
Necesario para animar el movimiento de un elemento a lo largo de un camino. animateMotion soporta los atributos animado y tiene 3 de su propio - ruta , la rotación , Keypoints .Opciones para definir una trayectoriaPuede definir una trayectoria de movimiento de varias maneras: use los atributos familiares de , para , por o valores , el nuevo atributo de ruta o una etiqueta secundaria <mpath> . He enumerado formas de aumentar la prioridad y las explicaré en el mismo orden.A los atributos de , a, Por especifica las coordenadas de puntos, los valores de la misma, pero ya en una lista <animateMotion from="0,0" to="50,100" .../> <animateMotion values="0,0; 0,100; 100,100; 0,0" .../>
El efecto de este método es comparable a la transformación habitual del desplazamiento. Un elemento se mueve rectilíneamente de un punto a otro. Y aquí, al igual que en animateTransform , las coordenadas son relativas . El punto 0,0 no indica la esquina superior izquierda del documento, sino la posición actual del elemento de destino. Esta característica está presente en otros métodos para determinar la trayectoria.El atributo de ruta especifica un conjunto de comandos, como para el atributo d . Si en el atributo d los comandos se interpretan como el contorno de la figura, en el atributo de ruta son la línea a lo largo de la cual se moverá el elemento. Las coordenadas de los puntos también son relativas, por lo que la ruta comienza en el punto 0,0 <animateMotion path="M 0 0 c 3.4 -6.8 27.8 -54.2 56 -37.7 C 73.3 -27.5 89.6 -5.1 81.9 5.9 c -5.8 8.3 -24.7 8.7 -45.4 -0.4" .../>
Este camino describe tal curvaLa última forma es utilizar un elemento <path> de terceros como ruta . Para hacer esto, debe especificar un enlace a este elemento en la etiqueta <mpath> , y la etiqueta misma debe colocarse dentro de <animateMotion> . Esta opción tiene la misma característica con coordenadas relativas. En esencia, este método "copia" el valor del atributo d del elemento en el atributo <path> <path id="movement" .../> ... <animateMotion ...> <mpath href="#movement"/> </animateMotion>
Es posible que el elemento que define la ruta ni siquiera aparezca en el documento. Simplemente puede definirlo en <defs>Girar un elemento en relación con la trayectoria.Es posible hacer que el elemento gire en la dirección del movimiento utilizando el atributo rotar . Acepta 3 tipos de valores: auto , auto-reverse y un número que indica rotación en grados <animateMotion rotate="auto" .../>
Por defecto, rotar es 0. Cualquier valor numérico captura el ángulo a lo largo de la animación. Modo automático auto y auto-reverse cambiar el elemento ángulo tangencial, respectivamente, a la trayectoria. Y difieren en la dirección de esta tangente. En automático, se dirige hacia adelante, mientras que en retroceso automático , se dirige hacia atrás.¿Cómo controlar el movimiento a lo largo del camino?La trayectoria es una curva que tiene un principio y un final, estos puntos se denotan con los números 0 y 1, respectivamente. Cualquier posición en la curva se puede determinar mediante un número en este rango. Al enumerar los puntos en el atributo keyPoints , puede definir cualquier tipo de movimiento a lo largo del camino. Pero esto no es suficiente para controlar el movimiento, para esto necesitas un sistema completo de atributos.Primero debe establecer calcMode en lineal o spline . A diferencia de otras etiquetas, animateMotion está predeterminado en ritmo (por alguna razón, la animación no quiere funcionar en este modo). También debe especificar un atributo.tiempos clave . Solo completando estos pasos, la animación funcionará como debería <animateMotion keyPoints="0.5; 1; 0; 0.5" keyTimes="0; 0.25; 0.75; 1" calcMode="linear" .../>
En el ejemplo, la animación comienza en el medio del camino, se mueve hasta el final, luego al principio y finaliza el movimiento nuevamente en el medioPSAl tratar con animateMotion , me encontré con información que se puede hacer lo mismo en CSS. Pero al final de este artículo, no tenía ni la fuerza ni el deseo de lidiar con esto. Para los entusiastas, solo dejo un enlace a la documentación.Agradecimiento especial
Bhudh por el tremendo trabajo en la corrección del artículo.