En el artículo anterior aprendimos a utilizar las propiedades offset
para definir trayectos animables. Ahora vamos a aprender a utilizar la función ray()
, que es una de las formas para crear trayectos utilizables con la propiedad offset-path
.
¿Qué hace la función ray()
?
La función ray()
nos permite definir un trayecto como una porción de un círculo, es decir, recorriendo una ruta del radio de un círculo, estableciendo un ángulo como hacemos al dibujar con CSS un gradiente cónico.
Observa la siguiente imagen, donde he dibujado un trazo discontinuo para representar un círculo (rojo) y los trayectos de esas porciones (negro) del círculo. En este caso tenemos 3 elementos .box
dentro de un .container
con un ángulo diferente cada uno:
En este ejemplo cada una de las cajas utiliza el siguiente ángulo:
- La primera caja (violeta) tiene un
ray()
con ángulo de90deg
(equivale a0.25turn
). - La segunda caja (rojo) tiene un
ray()
con ángulo de180deg
(equivale a0.5turn
). - La tercera caja (rosa) tiene un
ray()
con ángulo de245deg
(equivale a0.68turn
).
En este caso, sólo estamos utilizando el ángulo en la función ray()
, su sintaxis más simple. También se puede definir el tamaño con una de las palabras clave closest-side
, closest-corner
, farthest-side
, farthest-corner
o sides
. Si no se indica ninguna, se asume el valor closest-side
.
La función ray()
tiene más parámetros, pero veamos el ejemplo anterior de la imagen en código, junto a lo que hemos aprendido hasta ahora:
.container {
display: flex;
justify-content: center;
align-items: center;
background: #aaa;
min-height: 400px;
}
.box {
width: 50px;
height: 50px;
animation: move 2s alternate infinite;
}
@keyframes move {
0% { offset-distance: 0%; }
100% { offset-distance: 100%; }
}
.box-1 {
background: indigo;
offset-path: ray(90deg);
}
.box-2 {
background: crimson;
offset-path: ray(180deg);
}
.box-3 {
background: deeppink;
offset-path: ray(245deg);
}
<div class="container">
<div class="box box-1"></div>
<div class="box box-2"></div>
<div class="box box-3"></div>
</div>
La función ray()
Ahora que tenemos una idea de la función ray()
, veamos su sintaxis desde la más simple hasta la más compleja. Podemos añadir sólo su ángulo, como añadir también su tamaño, posición e incluso si queremos mantenerla dentro del contenedor:
Valores | Descripción |
---|---|
ray( ) | Indica un segmento en dirección |
ray( ) | Idem, pero con un tamaño predefinido |
ray( ) | Idem, pero colocando el elemento en una posición |
ray( contain) | Idem, pero manteniendo el elemento dentro del contenedor. |
Pero todo esto es mucho más fácil verlo con un ejemplo. Observa la siguiente demo interactiva, donde puedes modificar en vivo el ángulo, el tamaño y la opción contain
. Aunque no se muestra en la demo, también se podría añadir la posición tras la palabra clave at
para colocar de forma estática el elemento en una posición concreta:
.container {
width: 400px;
height: 400px;
display: grid;
place-items: center;
margin: auto;
border-radius: 50%;
background: #aaa;
& .box {
width: 50px;
height: 50px;
background: indigo;
offset-path: ray(0.25turn);
animation: move 2s alternate infinite;
}
}
@keyframes move {
0% { offset-distance: 0%; }
100% { offset-distance: 100%; }
}
label {
display: block;
font: monospace;
}
code {
position: absolute;
top: 1rem;
right: 1rem;
}
const size = document.querySelector("select.size");
const output = document.querySelector("output");
const input = document.querySelector("input");
const box = document.querySelector(".box");
const code = document.querySelector("code");
const contain = document.querySelector(".contain");
const update = () => {
const sizeValue = size.options[size.selectedIndex].value;
const containValue = contain.checked ? " contain" : "";
output.textContent = input.value + "turn";
const rayValue = `ray(${output.textContent} ${sizeValue}${containValue})`;
box.style.setProperty("offset-path", rayValue);
code.textContent = `offset-path: ${rayValue}`;
}
input.addEventListener("input", () => update());
size.addEventListener("input", () => update());
contain.addEventListener("input", () => update());
<label>
Angle: <input type="range" min="0" max="1" step="0.05" value="0.25">
<output>0.25turn</output>
</label>
<label>
Size: <select class="size">
<option value="closest-side">closest-side</option>
<option value="farthest-side">farthest-side</option>
<option value="closest-corner">closest-corner</option>
<option value="farthest-corner">farthest-corner</option>
<option value="sides">sides</option>
</select>
</label>
<label>
Contain: <input class="contain" type="checkbox">
</label>
<code>offset-path: ray(0.25turn)</code>
<div class="container">
<div class="box"></div>
</div>
Si no sabes como funcionan los parámetros de
mencionados anteriormente, echa un vistazo a formas y tamaños del gradiente radial, ya que lo explicamos ahí más detalladamente.
La propiedad offset-position
La propiedad offset-position
nos permite establecer la posición del trayecto. Esto puede ser útil en casos donde nos interesa posicionar el elemento dependiendo del trayecto que se utilice.
Valor | Descripción |
---|---|
auto | El valor auto es el valor por defecto. |
Indicamos la distancia a mover la posición inicial del trayecto. |
Veamos un ejemplo interactivo en acción. Observa que 100% 100%
, es decir, esquina inferior-derecha:
body {
min-height: 275px;
}
.container {
width: 500px;
height: 200px;
margin: auto;
background: grey;
}
.element {
width: 50px;
height: 50px;
background: indigo;
offset-path: ray(25deg);
offset-position: 0% 0%;
animation: move 2s alternate infinite linear;
}
@keyframes move {
to { offset-position: 100% 100%; }
}
const position = document.querySelector("select");
const element = document.querySelector(".element");
position.addEventListener("input", () => {
const offsetPosition = position[position.selectedIndex].textContent;
element.style.setProperty("offset-position", offsetPosition);
});
<label>
<code>offset-position (inicial): </code>
<select>
<option checked>0% 0%</option>
<option>50% 0%</option>
<option>100% 0%</option>
<option>50% 50%</option>
<option>0% 100%</option>
<option>50% 100%</option>
</select>
</label><br>
<code>offset-position (final): 100% 100%</code>
<div class="container">
<div class="element"></div>
</div>
Observa que en la animación sólo hemos establecido el to
, es decir, la posición final. Esto hará que se mueva hacia esa posición, partiendo del valor que tenía offset-position
en el elemento previamente.