Hola Mundo.
El ejercicio del día #2 requirió utilizar animaciones. Las cuales no estoy muy familiarizado. El objetivo de este reto es entender y comprender el mundo que es el CSS.
Day 2
Código base del reto
HTML
<div class="frame">
<div class="center">
<p>Happy coding :)</p>
</div>
</div>
CSS
// delete the following line if no text is used
// edit the line if you wanna use other fonts
@import url(https://fonts.googleapis.com/css?family=Open+Sans:700,300);
// use only the available space inside the 400x400 frame
.frame {
position: absolute;
top: 50%;
left: 50%;
width: 400px;
height: 400px;
margin-top: -200px;
margin-left: -200px;
border-radius: 2px;
box-shadow: 4px 8px 16px 0 rgba(0,0,0,0.1);
overflow: hidden;
background: #fff;
color: #333;
font-family: 'Open Sans', Helvetica, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
1. Identificar los elementos del reto
El elemento cuenta con 4 contenedores.
El contenedor principal sirve para contener 3 contenedores con estilo de líneas.
De igual manera se pueden identificar alrededor de 6 animaciones, 2 animaciones por línea
Al momento de darle clic, el primero y última línea se desplazan al centro, después de llegar rotan para quedar en diagonal y formar una X. La línea de en medio se encoge mientras cambia su opacidad.
Una vez toma la forma de X Al darle clic pasa a su forma original de la manera inversa.
2. Maquetación de los elementos
Para el contenedor principal cree un div al cual le asigne un, Id para posteriormente acceder a él mediante JS, la clase btn para aplicar estilos. A sí como él role button que sería el papel que plantea el reto un botón de menú de hamburguesa
Para las líneas les asigné dos clases, una de ellas la comparten esta contaría y la segunda para identificar a cada uno por separado.
<div id="btn-1" class="btn" role="button">
<div class="line line-1"></div>
<div class="line line-2"></div>
<div class="line line-3"></div>
</div>
3. Estilos básicos.
Para el diseño del contenedor principal. Opte por hacer uso de display flex para facilitar el acomodo de los elementos
Dejo un recurso rápido del uso de flexbox
btn {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 80px;
height: 52px;
}
.btn .line {
background: white;
width: 80px;
height: 8px;
border-radius: 3px;
box-shadow: 0 0 13px 0 rgba(0, 0, 0, 0.3);
}
.btn:hover {
cursor: pointer;
}
Resultado de la aplicación de estilos
4. Animación de entrada
La animación de entrada de la línea 1 y línea 3 se dividen en dos.
- Desplazamiento al centro.
- Rotación diagonal.
Mientras que la línea 3 escala su tamaño mientras baja su opacidad.
Para realizar esto haré uso de keyframes
De manera resumida, los keyframes nos permite definir estilos de css por frame para la creación de animaciones.
Animación de la línea 1 y 3
Para este caso definí el 70% y 100%. El 0% sería la posición inicial.
- 70% Traslada en el eje y 21 píxeles.
- 100% Rota la línea -45 grados y termina de acomodar la linea para centrarla.
En el caso del translate que agregue en el 100% lo hice a ojo mirando que la X que se forma se mirara céntrica.
Para la línea 3 el translareY es negativo, ya que va de abajo hacia arriba.
/* Linea 1 */
@keyframes moveTopToCenter {
70% {
transform: translateY(21px);
}
100% {
transform: rotate(-45deg) translateY(17px) translateX(-14px);
}
}
/* Linea 3 */
@keyframes moveBottomToCenter {
70% {
transform: translateY(-21px);
}
100% {
transform: rotate(45deg) translateY(-14px) translateX(-15px);
}
}
Animación de la línea 3
Para esta línea fue un scale de 1 a 0, agregando opacidad de 0.7 al 50% para evitar que se visualiza muy transparente a la mitad de la animación para al 100% ser de 0
@keyframes reduce {
0% {
transform: scale(1);
}
50% {
transform: scale(0.7);
opacity: 0.7;
}
100% {
transform: scale(0);
opacity: 0;
}
}
Para el manejo de tiempo de animación, cree otra clase llamada animated. La cual uso para aplicarle a todas la misma duración.
.animated {
animation-duration: 1s;
animation-fill-mode: both;
}
La idea de hacerlo de est amanera la aprendi de una libreria usada para la creacion de animaciones Animate CSS
Resultado después de la aplicación de los estilos
Para regresarlas a la forma anterior, aplique lo mismo pero a la inversa.
/* Linea 1 */
@keyframes leaveTopToCenter {
0% {
transform: rotate(-45deg) translateY(17px) translateX(-14px);
}
30% {
transform: rotate(0deg) translateY(21px) translateX(0px);
}
100% {
transform: translateY(0);
}
}
/* Linea 3 */
@keyframes leaveBottomToCenter {
0% {
transform: rotate(45deg) translateY(-14px) translateX(-15px);
}
30% {
transform: rotate(0deg) translateY(-21px) translateX(0px);
}
100% {
transform: translateY(0);
}
}
/* Linea 2 */
@keyframes expand {
0% {
transform: scale(0);
opacity: 0;
}
100% {
transform: scale(1);
opacity: 1;
}
}
5. JS para controlar la animación
Esta fue mi propuesta para el código donde al momento de darle clic al botón agrega las clases respectivas apara la transformación.
const btn1 = document.getElementById("btn-1");
const lines = document.getElementsByClassName("line");
// Funcion para eliminar y agregar clases a elemetnos html
const classHelper = (elementHtml, classAdd, classRemove) => {
elementHtml.classList.add(classAdd);
elementHtml.classList.remove(classRemove);
};
// Funcion qencargada de disparar la animacion
const dispatchAnimation = () => {
const [line1, line2, line3] = lines;
if (line1.classList.contains("moveTopToCenter")) {
classHelper(line1, "leaveTopToCenter", "moveTopToCenter");
classHelper(line2, "expand", "reduce");
classHelper(line3, "leaveBottomToCenter", "moveBottomToCenter");
classHelper(line2, "d-block", "d-none");
} else {
classHelper(line1, "moveTopToCenter", "leaveTopToCenter");
classHelper(line2, "reduce", "expand");
classHelper(line3, "moveBottomToCenter", "leaveBottomToCenter");
// Al momento de terminar la animacion principal aplico estilos
// Para ocultar el linea 2
setTimeout(() => {
classHelper(line2, "d-none", "d-block");
}, 500);
}
};
btn1.addEventListener("click", () => {
const clasess = btn1.classList;
// Clase que utiliso para saber si actualmente se encuentra en transicion
if (clasess.contains("is-animating")) return;
// Agrego la clase de que se esta animando
btn1.classList.add("is-animating");
// Mando a llamar la funcion para aplicar al animacion
dispatchAnimation();
// Elimino la clase de que se esta animando.
setTimeout(() => {
btn1.classList.remove("is-animating");
}, 700);
});
Resultado final
Revisando la manera en que lo realiza la página de 100 días de CSS, a sí como videos de YouTube realizando el mismo ejercicio, encontré puntos de mejora en mi código para hacerlo más legible y óptimo.
Háganme saber en los comentarios si quieren un post analizando los cambios que se pueden aplicar y otras formas de realizar este reto del día dos.
Top comments (0)