Animaciones

En este apartado veremos algunas animaciones reutilizables que son muy comunes en el ambito del desarrollo web y que Bodystyle nos ofrece listas para usar.
Las animaciones son: FadeIn, FadeOut, SlideInUp, SlideInDown.

Introducción

Como todos los módulos de Bodystyle, es necesario disponer del archivo bodystyle.min.js agregado en el proyecto para poder utilizar las animaciones.
Luego, se llama a la función correspondiente aplicando el efecto deseado al elemento HTML que se quiera animar.

    
    const FadeIn = (idElemento) => {
        // Obtener el elemento por su ID
        let ele = document.getElementById(idElemento);
        
        // Si no existe return
        if(!ele)
            return

        // LLAMADO A LA FUNCIÓN DE ANIMACIÓN
        // BS.fadeIn ( elemento, duración en milisegundos, función callback opcional )
        BS.fadeIn(ele, 1000, () => {
            BS.Toast({
                html: "🎯 Animación FadeIn completada",
            })
        });
    }
    const FadeOut = (idElemento) => {

        // Obtener el elemento por su ID
        let ele = document.getElementById(idElemento);

        // Si no existe return
        if(!ele)
            return

        // LLAMADO A LA FUNCIÓN DE ANIMACIÓN
        // BS.fadeOut ( elemento, duración en milisegundos, función callback opcional )
        BS.fadeOut(ele, 1000, () => {
            BS.Toast({
                html: "🎯 Animación FadeOut completada",
            })
        });
    }
    
    // Función Slide Up
    const SlideUp = (idElemento) => {
        // Obtener el elemento por su ID
        let ele = document.getElementById(idElemento);
        if(!ele) // Si no existe
            return // return

        // LLAMADO A LA FUNCIÓN DE ANIMACIÓN
        // BS.slideUp ( elemento, duración en milisegundos, función callback opcional )
        BS.slideUp(ele, 500, () => {
            BS.Toast({
                html: "🎯 Animación SlideUp completada",
            })
        });
    }


    const SlideDown = (idElemento) => {
        // Obtener el elemento por su ID
        let ele = document.getElementById(idElemento);
        if(!ele) // Si no existe
            return // return
        // LLAMADO A LA FUNCIÓN DE ANIMACIÓN
        // BS.slideDown ( elemento, duración en milisegundos, función callback opcional )
        BS.slideDown(ele, 500, () => {
            BS.Toast({
                html: "🎯 Animación SlideDown completada",
            })
        });
    }

 Peligro

La animación slideUp y slideDown son funcionales, pero no están del todo pulidas. Se recomienda usarlas con precaución y testear su comportamiento en los distintos navegadores.

Funcionamiento

Ahora veremos el código que hace posible las animaciones.
Todas las animaciones utilizan la propiedad CSS opacity para el efecto de desvanecimiento (fade) y la propiedad height para el efecto de deslizamiento (slide).
Cada función toma tres parámetros: el elemento a animar, la duración de la animación en milisegundos y una función callback opcional que se ejecuta al finalizar la animación.

 Fade In

En el archivo del repositorio Animaciones.js encontraremos cuatro dunciones que permiten que las animaciones de esta sección funcionen.
La función fadeIn incrementa gradualmente la opacidad del elemento desde 0 hasta 1 durante el tiempo especificado.

    
    /**
     * Desvanece (fade‑in) un elemento mostrándolo con animación de opacidad.
     * @param {HTMLElement|NodeList} elemento El elemento a mostrar.
     * @param {number} [duration=300] Duración en milisegundos.
     * @param {Function} [callback] Función opcional que se ejecuta al terminar la animación.
     */
    export function fadeIn(elemento, duration = 300, callback) {
        if (!elemento) return;
        const el = (elemento instanceof NodeList) ? elemento[0] : elemento;
        if (!el || !(el instanceof HTMLElement)) return;
    
        // Asegurar que el elemento sea visible
        el.style.display = el.style.display === 'none' ? 'flex' : el.style.display || 'flex';
        el.style.opacity = '0';
    
        const animation = el.animate(
            [
                { opacity: '0' },
                { opacity: '1' }
            ],
            {
                duration: duration,
                easing: 'ease-in-out',
                fill: 'forwards'
            }
        );
        
        animation.onfinish = () => {
            el.style.opacity = '1';
            if (typeof callback === 'function') callback();
        };
    }

 Fade Out

La función fadeOut disminuye gradualmente la opacidad del elemento desde 1 hasta 0 durante el tiempo especificado.

    /**
     * Desvanece (fade‑out) un elemento ocultándolo con animación de opacidad.
     * @param {HTMLElement|NodeList} elemento El elemento a ocultar.
     * @param {number} [duration=300] Duración en milisegundos.
     * @param {Function} [callback] Función opcional que se ejecuta al terminar la animación.
     */
    export function fadeOut(elemento, duration = 300, callback) {
        if (!elemento) return;
        const el = (elemento instanceof NodeList) ? elemento[0] : elemento;
        if (!el || !(el instanceof HTMLElement)) return;

        const animation = el.animate(
            [
                { opacity: '1' },
                { opacity: '0' }
            ],
            {
                duration: duration,
                easing: 'ease-in-out',
                fill: 'forwards'
            }
        );

        animation.onfinish = () => {
            el.style.opacity = '0';
            el.style.display = 'none';
            if (typeof callback === 'function') callback();
        };
    }

 Slide Up

La función slideUp reduce gradualmente la altura del elemento hasta 0, ocultándolo de la vista.

    /**
     * Desliza (slide‑up) un elemento ocultándolo con animación.
     * @param {HTMLElement|NodeList} elemento El panel a cerrar (puede ser un HTMLElement o un NodeList con un solo elemento).
     * @param {number} [duration=300] Duración en milisegundos.
     * @param {Function} [callback] Función opcional que se ejecuta al terminar la animación.
     */
    export function slideUp(elemento, duration = 300, callback) {
        if (!elemento) return;
        const el = (elemento instanceof NodeList) ? elemento[0] : elemento;
        if (!el || !(el instanceof HTMLElement)) return;

        // Cancelar animaciones previas para evitar conflictos
        if (el.__slideAnimation) {
            el.__slideAnimation.cancel();
        }

        // Asegurar que el elemento sea visible para obtener su altura actual
        const wasHidden = el.style.display === 'none';
        if (wasHidden) {
            el.style.display = 'block';
        }

        const startHeight = el.scrollHeight;
        el.style.overflow = 'hidden';
        el.style.opacity = '1';

        const animation = el.animate(
            [
                { height: `${startHeight}px` },
                { height: '0px' }
            ],
            {
                duration: duration,
                easing: 'ease-in-out',
                fill: 'forwards'
            }
        );

        el.__slideAnimation = animation;

        animation.onfinish = () => {
            el.style.display = 'none';
            el.style.removeProperty('height');
            el.style.removeProperty('overflow');
            el.__slideAnimation = null;
            if (typeof callback === 'function') callback();
        };
    }

 Slide Down

La función slideDown incrementa gradualmente la altura del elemento desde 0 hasta su altura original, mostrándolo en la vista.

    /**
     * Desliza (slide‑down) un elemento mostrándolo con animación.
     * @param {HTMLElement|NodeList} elemento El panel a abrir.
     * @param {number} [duration=300] Duración en milisegundos.
     * @param {Function} [callback] Función opcional que se ejecuta al terminar la animación.
     */
    export function slideDown(elemento, duration = 300, callback) {
        if (!elemento) return;
        const el = (elemento instanceof NodeList) ? elemento[0] : elemento;
        if (!el || !(el instanceof HTMLElement)) return;

        // Cancelar animaciones previas para evitar conflictos
        if (el.__slideAnimation) {
            el.__slideAnimation.cancel();
        }

        // Aseguramos que el elemento sea visible para calcular su altura natural
        el.style.display = 'block';
        el.style.overflow = 'hidden';
        el.style.height = '0px';
        el.style.opacity = '1';

        // Forzar reflow para que el cambio de display se aplique antes de animar
        void el.offsetHeight;

        const targetHeight = el.scrollHeight;

        const animation = el.animate(
            [
                { height: '0px' },
                { height: `${targetHeight}px` }
            ],
            {
                duration: duration,
                easing: 'ease-in-out',
                fill: 'forwards'
            }
        );

        el.__slideAnimation = animation;

        animation.onfinish = () => {
            el.style.removeProperty('height');
            el.style.removeProperty('overflow');
            el.style.removeProperty('opacity');
            el.__slideAnimation = null;
            if (typeof callback === 'function') callback();
        };
    }

Autor