Efecto confeti con JavaScript y CanvasConfetti

En este artíclulo veremos como añadir un efecto confeti con JavaScript y la librería CanvasConfetti. Mejorando así la experiencia de usuario, y agregando un factor sorpresa a nuestra aplicación web.

https://www.kirilv.com/canvas-confetti/ “🎉 on-demand confetti gun”

Para ver un caso práctico de la librería, he preparado un ejercicio al final del artículo. Haz click en la siguiente imagen para ver el resultado en una ventana nueva:

Ejercicio CanvasConfetti
Haz click sobre la imagen para ver el ejercicio acabado de éste tutorial

¿Quieres aprender a hacer este ejercicio? Saltar directamente al tutorial

En algún momento y en algún lugar del mundo, alguien debió preguntar: ¿Y si añadimos a nuestra aplicación un cañón que dispare confetti…?, y tras unos segundos de silencio, Kiril Vatev, ingeniero de software y desarrollador web se puso a crear CanvasConfetti.

Efectivamente, CanvasConfetti ofrece lo que promete. Una interfaz de desarrollo que permite a cualquier programador JavaScript importar y ejecutar un sistema de partículas que simula confeti disparado a voluntad. Y la verdad, es que lo resuelve de una forma excelente, dando como resultado un efecto “cool” con infinidad de aplicaciones.

Ésta librería no ocupa más de 16kb compilada. Y ha llegado a tal punto de popularidad, que en el momento de redactar este artículo, ya posee alrededor de 2300 estrellas en GitHub. A demás de ser avalada por una comunidad de casi 3200 personas. 

Por cierto, hay que parar un momento y hacer una especial mención al búho que aparece en el banner promocional de su página de Github.

Instala y empieza a disparar confeti como si no hubiera un mañana

Como es habitual, se ofrece la posibilidad de integrar CanvasConfetti mediante el conocido comando “npm install –save canvas-confetti”. Tras unos segundos de descarga, ya estamos en disposición de implementar la librería en nuestro proyecto.

Para ello, empezamos analizando los distintos ejemplos que nos brinda la home. De un rápido vistazo, vemos que con muy pocas líneas de código, podemos crear variaciones muy dispares. Desde un efecto de fuegos artificiales, hasta una suerte de nieve de confeti.

La librería viene con opciones predeterminadas. Sin embargo, su API permite el control del sistema de partículas, mediante parámetros como cantidad, colores, formas, gravedad, ángulo o propagación entre otros.

Para ello, solo se tiene que acompañar la llamada a la librería con un objeto JSON. Ese argumento debe contener los nombres y valores de las propiedades que se quieren configurar.

Sorprende cómo, modificando unos pocos parámetros, se puede dotar al sistema, de una expresividad y de un comportamiento determinados.

Este recurso, es ideal para utilizar en aplicaciones web con un factor de progresión y gamificación. Un buen ejemplo sería en una plataforma web de cursos online, donde tras completar cada lección, se lanza una animación de confeti. En ese contexto, se mejoraría la experiencia de usuario, reforzando la sensación de éxito y recompensa para el usuario.

Vamos a darle vida al emoji 🎉!

A continuación crearemos un simple botón que al hacer click dispara confeti. A pesar de no ser un gran ejercicio, muestra cómo de sencillo es poner en marcha la librería.

Para ello, empezaremos con una estructura HTML simple. Sencillamente crearemos un botón que contenga el conocido emoji de la pistola de confeti y un toolip.

    <button class="canvas-confetti-btn animate__animated">
      🎉
      <span class="tool-tip">Click me!</span>
    </button>

Centraremos y ampliaremos el botón que hemos creado mediante el siguiente código CSS.

@import "animate.css";
@import url("https://fonts.googleapis.com/css2?family=Outfit:wght@100;400;700&display=swap");
html {
  height: 100%;
  body {
    height: 100%;
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
    align-items: center;
  }
}
.canvas-confetti-btn {
  font-size: 5rem;
  border: none;
  background-color: transparent;
  cursor: pointer;
  position: relative;
  .tool-tip {
    opacity: 1;
    transition: opacity 0.2s ease-in-out;
    animation: shake 3s cubic-bezier(0.36, 0.07, 0.19, 0.97) infinite;
    position: absolute;
    top: -40px;
    left: 0;
    width: 100%;
    background-color: #fff;
    color: #000;
    font-weight: 400;
    padding: 5px;
    border-radius: 4px;
    box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
    font-size: 1rem;
    color: rgb(100, 100, 100);
    &:after {
      content: "";
      position: absolute;
      left: 50%;
      margin-left: -8px;
      bottom: -5px;
      background-color: #fff;
      transform: rotate(45deg);
      width: 10px;
      height: 10px;
    }
  }
  &:hover {
    .tool-tip {
      animation: none;
      opacity: 0;
    }
  }
}
@keyframes shake {
  10%,
  90% {
    transform: translate3d(0, 0, 0);
  }
  20%,
  80% {
    transform: translate3d(0, 0, 0);
  }
  30%,
  50%,
  70% {
    transform: translate3d(0, -4px, 0);
  }
  40%,
  60% {
    transform: translate3d(0, 4px, 0);
  }
}

Finalmente, mediante JavaScript, definimos el siguiente comportamiento.

Empezamos importando la librería y guardamos una referencia al botón en el DOM.

import confetti from "canvas-confetti";
const confettiBtn = document.querySelector(".canvas-confetti-btn");

Declaramos una variable de control, llamada “exploding” para evitar múltiples disparos demasiado seguidos.

let exploding = false;

Construimos una función “fire”. Ésta, ejecutará “confetti”, combinando parámetros generales con valores que le pasaremos en forma de argumento.

const defaults = {
  particleCount: 500,
  spread: 80,
  angle: 50,
};
const fire = (particleRatio, opts) => {
  confetti(
    Object.assign({}, defaults, opts, {
      particleCount: Math.floor(defaults.particleCount * particleRatio),
    })
  );
};

Solo queda conectar la acción de “click” del botón, con una función de “callback”. En esa función ejecutamos varias veces “fire”, y reseteamos la boleana “exploding” a través de dos temporizadores.

confettiBtn.addEventListener("click", () => {
  if (exploding) {
    return;
  }
  exploding = true;
  confettiBtn.classList.add("animate__rubberBand");
  window.setTimeout(() => {
    fire(0.25, {
      spread: 26,
      startVelocity: 55,
    });
    fire(0.2, {
      spread: 60,
    });
    fire(0.35, {
      spread: 100,
      decay: 0.91,
      scalar: 0.8,
    });
    fire(0.1, {
      spread: 120,
      startVelocity: 25,
      decay: 0.92,
      scalar: 1.2,
    });
    fire(0.1, {
      spread: 120,
      startVelocity: 45,
    });
    window.setTimeout(() => {
      confettiBtn.classList.remove("animate__rubberBand");
      exploding = false;
    }, 300);
  }, 300);
});

Adicionalmente se ha añadido la librería css animate. Para conseguir mejorar la respuesta del botón tras presionarlo.

Aunque inicialmente me pareció gracioso que una librería cubriera una necesidad tan peculiarmente específica. La verdad es que CanvasConfetti es un excelente ejemplo de microlibrería bien resuelta.

Efectos para un mejor «engagement»

Como se suele decir, dios está en los detalles, y librerías como CanvasConfetti, contribuyen a llevar nuestros proyectos un poco más lejos. Aportando pequeñas experiencias que mejoran la respuesta emocional de los usuarios.

En ese sentido me recuerda ligeramente a Atropos y a CountUp. Tal y como vimos, són la mejor opción si se busca implementar efectos específicos.

Actualización: Recientemente he analizado la librería FireworksJs para crear efectos de fuegos artificiales, si te ha gustado CanvasConfetti, no te puedes perder esta otra biblioteca.

Crear efectos de fuegos artificiales con JavaScript y FireworksJs

Este ha sido un pequeño vistazo a la librería CanvasConfetti. A continuación os dejo enlaces a más recursos, así como el ejercicio subido al repositorio de Github de “Librerías Js”.

Nos vemos en el próximo vídeo, un abrazo desarrolladores!

2 comentarios en «Efecto confeti con JavaScript y CanvasConfetti»

Deja un comentario