¿Qué son los trayectos animados?

CSS Motion Path: Trayectos animables


En CSS existen los trayectos animados, también denominados como Motion Paths. Se trata de una característica mediante la cuál podemos crear de forma muy sencilla trayectos, rutas o caminos por los que animamos un elemento.

Propiedades de trayectos animables

Para crear estos trayectos debemos realizar dos tareas. En primer lugar, definir el trayecto. En segundo lugar, crear la animación para mover un elemento a través de dicho trayecto, definiendo su punto de partida y su punto final.

Para hacer esto, se utilizan una serie de propiedades CSS prefijadas por offset-, que son las que veremos en este artículo y tienen resumidas en la siguiente tabla:

Propiedad Descripción Más información
offset-path Define un trayecto, ruta o camino.
offset-distance Indica la posición actual en el trayecto.
offset-position Define el punto de inicio del trayecto. Ver offset-position
offset-rotate Define la orientación del elemento del trayecto.
offset-anchor Define el punto de anclaje (punto de origen) del elemento que se mueve por el trayecto.
offset Propiedad de atajo de las anteriores.

Vayamos viendo cada una de estas propiedades CSS para entenderlas correctamente.

Definir un trayecto

Probablemente, la parte más importante de los Motion Paths (trayectos animados) es definir un trayecto mediante la propiedad offset-path. Este trayecto creará el camino por el que se puede mover el elemento que animaremos más adelante.

Hay varias formas de crear trayectos con offset-path. En este artículo vamos a utilizar la función polygon(), que pertenece a las formas básicas, pero es muy recomendable echar un vistazo luego a estos artículos para conocer más formas de crear trayectos.

La propiedad offset-path nos permite definir un trayecto de varias formas:

Forma Descripción
none No establece ningún trayecto. Es el valor por defecto.
Forma básica CSS Una forma básica, mediante funciones como xywh(), circle(), polygon() o similares.
Función ray() Permite definir trayectos como porciones de un círculo (ángulo cónico).
Función path() Permite definir trayectos mediante rutas de SVG
Función url() Permite definir trayectos mediante ficheros externos SVG.

Como hemos dicho, en este artículo vamos a utilizar la función polygon(), que sirve para definir un polígono imaginario, indicando los puntos x,y por donde vamos creando el polígono. Nuestro .element se moverá a través de un rectángulo invisible definido por polygon():

.element {
  --size: 50px;

  width: var(--size);
  height: var(--size);
  background: indigo url("robot.png");
  background-size: var(--size);
  border-top: 5px solid deeppink;
  offset-path: polygon(0 0, 350px 0, 350px 100px, 0 100px);
  animation: move 5s infinite linear;
}

@keyframes move {
  0% { offset-distance: 0%; }
  100% { offset-distance: 100%; }
}
<div class="element"></div>

Observa que a .element le hemos añadido un borde superior rosa. Si te fijas, al seguir el trayecto, el elemento se va girando conforme al trayecto definido. Esto es importante y lo retomaremos más adelante.

Posición actual en el trayecto

Si observas el ejemplo anterior, en la animación move estamos utilizando la propiedad offset-distance, que nos permite indicar el tamaño o porcentaje actual, es decir, el fragmento recorrido en el trayecto desde la posición inicial.

En nuestro ejemplo definimos la animación desde el inicio (0%) hasta el final (100%), utilizando porcentajes que es la unidad más cómoda:

@keyframes move {
  0% { offset-distance: 0%; }
  100% { offset-distance: 100%; }
}

También podríamos utilizar otras unidades o, en lugar de una animación, gestionarlo mediante transiciones o código Javascript más personalizado.

Rotación del elemento

La propiedad offset-rotate se encarga de definir como vamos a rotar el elemento respecto a su trayecto. En apartados anteriores vimos que la rotación se realizaba de forma automática respecto a su posición en el trayecto. Este es el comportamiento si offset-rotate está establecido a auto.

Sin embargo, si modificamos offset-rotate con el valor 0deg, estaremos indicando al navegador que ese elemento no debería rotarse.

Los valores que puede tomar esta propiedad son los siguientes:

Valor Descripción
auto El valor auto es el valor por defecto. El elemento rota según el trayecto definido.
auto Prefijado del valor auto, se le suma el ángulo indicado en .
reverse El valor reverse es justo el inverso al valor auto.
reverse Idem a auto , pero justo el valor inverso.
Se establece exactamente el ángulo de rotación de .

Veamos un ejemplo utilizando la propiedad offset-rotate en la animación definida, donde le indicamos que vaya desde 90deg a 0deg:

.element {
  --size: 50px;

  width: var(--size);
  height: var(--size);
  background: indigo url("robot.png");
  background-size: var(--size);
  border-top: 5px solid deeppink;
  offset-path: polygon(0 0, 350px 0, 350px 100px, 0 100px);
  animation: move 5s infinite linear;
}

@keyframes move {
  0% {
    offset-distance: 0%;
    offset-rotate: 90deg;
  }
  100% {
    offset-distance: 100%;
    offset-rotate: 0deg;
  }
}
<div class="element"></div>

Obviamente, estos valores podemos modificarlos a nuestro criterio y elección, según nos interese.

Punto de anclaje

Mediante la propiedad offset-anchor podemos establecer un punto de origen para el elemento que se mueve en el trayecto. Por ejemplo, observa la siguiente imagen y ten en cuenta los valores indicados (valor de eje X y valor de eje Y).

  • El primero es 100% 100%: El punto que se moverá por el trayecto es la esquina inferior-derecha.
  • El segundo es 50% 50%: El punto que se moverá por el trayecto es el centro de la imagen.
  • El tercero es 50% 0%: El punto que se moverá por el trayecto es la antena del robot.

La propiedad offset-anchor

En este caso, estamos usando un trayecto definido con la función path(), que explicaremos un poco más adelante. Básicamente, crea un camino basado en un trayecto SVG. Luego, con la propiedad offset-anchor definimos su punto de anclaje:

.element {
  --size: 50px;

  width: var(--size);
  height: var(--size);
  background: indigo url("robot.png");
  background-size: var(--size);
  border-top: 5px solid deeppink;
  offset-path: path("m 50 50 h 350 v 100");
  offset-anchor: 50% 50%;
  animation: move 5s infinite linear;
}

@keyframes move {
  0% { offset-distance: 0%; }
  100% { offset-distance: 100%; }
}
<div class="element"></div>

Observa que al haber definido 50% 50%, la rotación la hace sobre el centro de la imagen del robot.

Atajo: La propiedad offset

Por último, como muchas otras propiedades CSS, podemos utilizar la propiedad de atajo offset que nos permite escribir todas las propiedades individuales que hemos visto, desde una misma propiedad, algo que en muchas ocasiones nos resulta muy cómodo:

.box {
  /* offset: <position> <path> <distance> <rotate> / <anchor>; */

  offset: path("m 0 0 h 100 v 200") 0% 45deg;
  offset: auto path("m 0 0 h 100 v 200") 0% 45deg / 50% 50%;
  offset: ray(45deg closest-side) / 40px 20px;
}

Observa que, en el primer y último ejemplo, omitimos la propiedad offset-position, ya que no nos interesa indicarla (la explicaremos en el próximo artículo). La propiedad offset-anchor en el primer ejemplo, también la hemos omitido. De necesitar usarla, habría que añadir sus valores, precedidos del carácter /.

En el próximo artículo nos centraremos en aprender a crear trayectos utilizando la función ray(), que nos permitirá definir porciones de un círculo.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev