Crear presentaciones con JavaScript y RevealJs

Crear presentaciones en forma de pases de diapositivas es posible gracias a JavaScript y RevealJs. No volverás a abrir PowerPoint en la vida.

Hacia al final de éstos párrafos encontrarás un tutorial para crear un pase diapositivas “silder” con la librería RevealJs. Haz click en la siguiente imágen para ver el resultado final.

Ver ejercicio terminado en una ventana nueva.

Si quieres saltar a la parte práctica haz click aquí

Como parte de mi trabajo, además de programar, tengo que asistir a múltiples reuniones de equipo y clientes.

En ellas es habitual preparar presentaciones en forma de pase de diapositivas, para guiar y organizar el contenido que se va a exponer. 

Por lo general, crear este material es una tarea que se me antoja tediosa.

Personalmente prefiero invertir esfuerzos en otras cosas, y dejar las presentaciones en manos de quien se le dé mejor.

Pero como imaginarás, no siempre se puede elegir, y tarde o temprano tengo que diseñar algún que otro “slider” para que actúe de soporte en una reunión.

Código Frontend frente a programas de usuario para crear pases de diapositivas

Seguramente ya conocerás algunos programas para generar pases de imágenes y gráficos.

Entre los más populares, se encuentran Microsoft Power Point o Google Slides. Estos son softwares potentes y ofrecen una gran variedad de opciones para el usuario.

JS vs PowerPoint round one!
JS vs PowerPoint round one!

Sin embargo, si estás leyendo este blog, probablemente seas un desarrollador con conocimientos de programación frontend. Por eso, en este artículo te quiero enseñar una forma de creación de sliders, alternativa a las herramientas clásicas.

Estoy hablando de RevealJs.

Una librería JavaScript para construir pases de diapositivas, que te permitirá aprovechar tu conocimiento técnico, a la hora de generar presentaciones dinámicas en el navegador

RevealJs fue creada por Hakim El Hattab, con el objetivo de poner todo el potencial del desarrollo web, al servicio de charlas, ponencias o cualquier otro tipo de presentación.

En la actualidad, el repositorio «open source» de Github tiene más de 62.9K estrellas, y es mantenido por un equipo de 300 personas.

El paquete NPM se descarga más de 23K veces por semana.

Hakim ha logrado que crear un pase de «sliders» sea lo más parecido a programar una aplicación web.

Y lo mejor es que permite hacerlo de forma totalmente declarativa con resultados muy profesionales, tal y como veremos más adelante. 

Otro punto fuerte de ésta herramienta, es que permite añadir código JavaScript para cada «slide», de este modo se pueden integrar recursos propios y de terceros, como por ejemplo gráficos D3.

Como ves, se trata de una opción muy interesante. 

Si como yo, disfrutas más abriendo el Visual Studio Code que el Power Point, no te puedes perder el tutorial que he preparado al final de este escrito.

Declarar “slides” a base de etiquetas HTML 

Como empieza a ser habitual en este blog, acabaremos implementando un ejercicio práctico muy sencillo.

Pero antes, es necesario familiarizarse un poco con la API de ésta herramienta. Así que vamos a darle un rápido vistazo a sus capacidades

El comando NPM para instalar la librería es el siguiente:

npm install reveal.js

Una vez instalada, la forma más sencilla de uso es importando la clase Reveal, e instanciando un objeto “deck” a partir de ésta.

La clase Revel admite un objeto de configuración para customizar y definir ciertos comportamientos de la presentación. En seguida veremos qué parámetros acepta, y para qué sirven. 

El objeto “deck”, por su lado, permite llamar al método “initialize()” para desplegar la presentación.

Esa función devuelve una “promise”, que se resuelve cuando el programa ha inicializado por completo

const deck = new Reveal({
  hash: true,
  respondToHashChanges: true,
  history: true,
});
const launchPresentation = async () => {
  await deck.initialize();
  console.log("ready");
};
launchPresentation();

Existe una gran cantidad de parámetros que se pueden definir en el objeto de configuración. 

En el listado que sigue, solo voy a destacar los que me han parecido más interesantes, en cualquier caso, te dejo un enlace a la documentación, por si quieres estudiarlos todos detenidamente.

  • controls: variable booleana para mostrar u ocultar las fechas de control.
  • controlsLayout: asignandole una cadena de texto como «bottom-right», podemos posicionar dichos controles
  • progress: por defecto, Reveal mostrará una barra de progresión en la parte inferior. Con esta propiedad podemos desactivar este comportamiento.
  • hash: si se requiere que se pueda compartir una url en un punto determinado de la presentación, se puede habilitar un hash con el número del «slide» activo.
  • keyboard: de forma predefinida se puede utilizar el teclado para avanzar entre las diapositivas, con la propiedad «keyboard» se puede revertir esta opción. 

Como dije, existen muchas más, en ésta URL de la documentación oficial tienes acceso al resto de ellas:

https://revealjs.com/config/

Elegir el tema CSS que mejor se ajusta a tu estilo

Tras instanciar y declarar el comportamiento base de nuestro slider, es necesario definir el apartado gráfico

RevealJs viene con un conjunto de archivos CSS listos para que las presentaciones luzcan geniales.

Por un lado, es necesario importar un documento CSS base que se encarga de posicionar correctamente todos los elementos de forma «responsive».

Este archivo se encuentra en el siguiente directorio:

/node_modules/reveal.js/dist/reveal.css

Por otro lado, existen hasta doce temas, para que elijas el que mejor se ajusta a tu estilo.

Los temas se alojan en el siguiente directorio:

/node_modules/reveal.js/dist/dist/theme/black.css

Seguidamente te adjunto una URL al listado completo de temas disponibles

https://revealjs.com/themes/

Un slider declarativo gracias a las etiquetas HTML

Llegados a este punto, es posible que pienses, todo esto está genial, pero no tengo claro cómo generar el contenido de la presentación. 

Bien, como dije, se trata de una librería declarativa. Eso significa que tan solo añadiendo etiquetas HTML es suficiente para que la Reveal reconozca el contenido y la estructura.

Eso sí, es necesario respetar algunas convenciones para que funcione correctamente.

La estructura básica del documento debe tener un elemento padre con la clase «.reveal». Inmediatamente después tiene que contener un elemento hijo con la clase «.slides».

Éste segundo elemento agrupará tantas etiquetas «section» como queramos. Siendo cada sección un slide de la presentación. 

De este modo, la estructura más sencilla que se puede generar respondería a la siguiente maqueta HTML.

<div class="reveal">
  <div class="slides">
    <section>
      <h1>Esto es un slide</h1>
    </section>
    <section>
      <h1>Esto es otro slide</h1>
    </section>
  </div>
</div>

Una característica importante a mencionar, es que se pueden enmarcar otras etiquetas «section» dentro de una sección para generar diapositivas en vertical.

<div class="reveal">
  <div class="slides">
    <section> 
      <section>
        <h1>Esto es un slide</h1>
      </section>
      <section>
        <h1>Esto es un slide vertical</h1>
      </section>
    </section>
  </div>
</div>

Personalización mediante atributos data

Como supondrás, RevealJs también contempla la personalización a nivel de diapositiva.

Tras definir un tema global y unas características generales, es posible editar ciertos acabados de cada «section».

Para lograrlo, RevealJs habilita una serie de atributos de tipo «data-« para asignar a las etiquetas que se desee.

A continuación veremos algunos de estos atributos, los valores que aceptan y su utilidad.

  • data-transition: A pesar de que en el objeto config de puede asignar las transiciones generales entre diapositivas, con éste parámetro se puede definir una distinta para una determinada sección
  • data-background-color: Tal y como su nombre indica permite asignar un color de fondo específico. Cabe mencionar que también se pueden asignar degradados, imágenes o incluso vídeos. Descubre todas las posibilidades en la documentación oficial.
  • data-src: Éste atributo se puede asignar a cualquier etiqueta que cargue contenido multimedia. Con ello, se logra que el recurso en cuestión se muestre sólo en el momento de visualizarlo, evitando así peticiones innecesarias y mejorando el rendimiento.
  • data-fragment-index: Gracias a la clase «.fragment» se pueden declarar áreas nuevas de interacción antes de saltar al siguiente slide. Con el atributo data-fragment-índex, se puede reorganizar el orden de aparición de estos «fragments». Más información en este enlace
  • data-visibility: Si se desea inhabilitar una diapositiva, éste es el atributo necesario. 

Existen muchos otros atributos más, pero creo que este listado ilustra perfectamente el potencial de la herramienta.

Por supuesto, no dejes de consultar la documentación oficial para conocer más en profundidad las capacidades de la librería. 

Un pase de diapositivas basado en HTML

Ha llegado el momento de poner en práctica la API de RevealJs.

Y no se me ocurre una mejor forma, que creando una presentación sobre LibreríasJs, porque siempre viene bien un poco de autobombo.

Encontrarás una copia del ejercicio terminado, en el repositorio de libreriasjs:

//https://github.com/Danivalldo/libreriasjs/tree/master/RevealJs

Puedes utilizar este recurso como guía para seguir el tutorial que sigue.

La presentación que vamos a generar se compone principalmente de dos partes. En la primera, presentaré un poco el blog libreriasjs.

En la segunda aprovecharé para mostrar otros recursos HTML5, ilustrando así la capacidad de Reveal para cargar librerías de terceros.

Para ello instalamos las dependencias necesarias con el siguiente comando:

npm i @google/model-viewer @lottiefiles/lottie-player particlesjs reveal.js
  • @google/model-viewer permite visualizar elementos 3d en el navegador
  • @lottiefiles/lottie-player permite cargar y manipular animaciones SVG
  • particlesjs permite simular un sistema de partículas en una etiqueta canvas

Empezamos definiendo la estructura HTML. Recuerda que todas las secciones se deben enmarcar dentro ésta estructura base:

<div class="reveal">
  <div class="slides">
  </div>
</div>

Preparamos el contenido de la primera parte de la presentación, construyendo cuatro secciones, como las que te presento a continuación.

En la primera sección mostramos el título, la descripción y el nombre de quien realiza la presentación.

<section>
  <h1 class="text-aquamarine">LibreriasJs</h1>
  <p class="fragment">
    <a href="https://libreriasjs.com">libreriasjs.com</a>
  </p>
  <p class="fragment">Tu web de referencia 👩‍💻</p>
  <small class="fragment">por Dani Valldosera</small>
</section>

La clase “.fragment” indicará a Reveal que debe animar la entrada del contenido, antes de saltar al siguiente slide.

Acto seguido, seguimos con un slide dedicado a captar la atención del usuario, para ello animamos cuatro frases consecutivamente.

<section>
  <div class="">Aprende</div>
  <div class="fragment">todo tipo</div>
  <div class="fragment">de <b>librerias y recursos</b></div>
  <h2 class="fragment text-aquamarine">JavaScript</h2>
</section>

En la tercera sección listamos una serie de enlaces a artículos relevantes del blog.

<section>
  <section>
    <h3>Estos son algunos de los artículos más interesantes:</h3>
    <ul class="fragment">
      <li>
        Crear pdfs con JsPDF <br />
        <a
          href="https://libreriasjs.com/libreria-javascript-crear-pdf-jspdf/"
          rel="nofollow"
          target="_blank"
          >Artículo</a
        >
        <a
          href="https://libreriasjs.com/exercises/js-pdf/"
          rel="nofollow"
          target="_blank"
          >Demo</a
        >
      </li>
      <li>
        Valida formularios con Yup <br />
        <a
          href="https://libreriasjs.com/libreria-javascript-validar-formularios-yup/"
          rel="nofollow"
          target="_blank"
          >Artículo</a
        >
        <a
          href="https://libreriasjs.com/exercises/yup/"
          rel="nofollow"
          target="_blank"
          >Demo</a
        >
      </li>
      <li>
        Crea un juego de ajedrez con ChessJs <br />
        <a
          href="https://libreriasjs.com/libreria-javascript-ajedrez-chessjs/"
          rel="nofollow"
          target="_blank"
          >Artículo</a
        >
        <a
          href="https://libreriasjs.com/exercises/chessjs/"
          rel="nofollow"
          target="_blank"
          >Demo</a
        >
      </li>
    </ul>
    <p class="fragment">
      <small>
        <a
          href="https://github.com/Danivalldo/libreriasjs/blob/master/README.md"
          target="_blank"
          rel="nofollow"
          >y mucho más...</a
        >
      </small>
    </p>
  </section>
</section>

Y antes de saltar a la segunda parte de la presentación, generamos expectativa con una frase introductoria.

<section>... Y muy pronto veremos herramientas para...</section>

Entramos en la segunda fase de la presentación mostrando ejemplos de librerías nuevas. 

Esta fase permitirá navegar en vertical, así que anidaremos “sections” dentro de otras etiquetas “section”. 

También modificaremos el tipo de transición y el color de fondo, con los atributos data-transition y data-background-color.

Comenzamos preparando la diapositiva para mostrar un sistema de partículas.

<section>
  <section>
    <h4>Animar Partículas</h4>
    <p>👇</p>
  </section>
  <section data-transition="zoom" data-background-color="aquamarine">
    <canvas class="background-particles"></canvas>
  </section>
</section>

No te preocupes por el contenido, veremos cómo implementar las dependencias que hemos instalado más adelante.

Seguidamente dejamos preparado el “slide” para mostrar animaciones SVG con Lottie.

<section>
  <section>
    <h4>Animar imágenes en formato SVG</h4>
    <p>👇</p>
  </section>
  <section data-transition="zoom" data-background-color="aquamarine">
    <div>
      <div class="lottie-container">
        <lottie-player
          autoplay
          controls
          loop
          mode="normal"
          src="./lottie-animations/135022-jellyfish.json"
          style="width: 320px"
        >
        </lottie-player>
      </div>
      <div class="credit">
        Animation by
        <a
          href="https://lottiefiles.com/ak1kti1z55xybn7p"
          target="_blank"
          rel="nofollow"
          >Matt Bruning</a
        >
      </div>
    </div>
  </section>
</section>

Por último, pero no por ello menos importante, construimos el código para renderizar elementos 3d con la etiqueta “model-viewer”.

<section>
  <section>
    <h4>O visualizar gráficos en 3d</h4>
    <p>👇</p>
  </section>
  <section data-transition="zoom" data-background-color="aquamarine">
    <div>
      <model-viewer
        class="model-viewer"
        alt="Suzanne"
        src="./model/suzanne.gltf"
        shadow-intensity="1"
        camera-controls
        touch-action="pan-y"
        auto-rotate
      ></model-viewer>
    </div>
  </section>
</section>

Cerramos la presentación por todo lo alto, añadiendo un gif de gatos y una frase de concienciación.

<section>
  <h2>Fin</h2>
  <iframe
    src="https://giphy.com/embed/BzyTuYCmvSORqs1ABM"
    width="400"
    height="400"
    frameborder="0"
    class="giphy-embed"
    allowfullscreen
  ></iframe>
  <p>Utiliza este poder con responsabilidad</p>
</section>

Cuando importemos RevealJs al proyecto, éste reconocerá la estructura HTML, y construirá el pase de sliders por nosotros.

Pero primero, definimos unos estilos y un tema base para la presentación.

Crea un archivo style.sass e importa los recursos css que Reveal te ofrece. En mi caso he seleccionado el tema “black”.

@import  'reveal.js/dist/reveal.css'
@import  'reveal.js/dist/theme/black.css'

Añade algunos estilos adicionales como los que siguen:

.reveal
  .model-viewer
    display: block
    width: 100%
    height: 700px
  .text-aquamarine
    color: aquamarine
  a
    color: #191919
    display: inline-block
    padding: 0 10px
    font-size: .8em
    border-radius: 4px
    background-color: aquamarine
    &:hover
      background-color: #aff5de
      color: #191919
  .lottie-container
    max-width: 400px
    margin: 0 auto
  .credit
    position: absolute
    right: 0
    bottom: 0
    font-size: 10px
    a
      font-size: 10px
      font-weight: bold
  .background-particles
    width: 100vw
    height: 100vh
  h1, h2, h3, h4, h5
    text-transform: initial

Ahora sí, ha llegado el momento de dar vida a la presentación. Crea un archivo “main.js” e importa todo lo necesario.

import "./style.sass";
import Reveal from "reveal.js";
import "@lottiefiles/lottie-player";
import Particles from "particlesjs";
import "@google/model-viewer";

Instancia la clase Reveal con algunas opciones de configuración. Si quieres poder navegar directamente a una diapositiva en concreto, debes agregar los siguientes parámetros.

const deck = new Reveal({
  hash: true,
  respondToHashChanges: true,
  history: true,
});

Guarda en una variable “deck” el objeto instanciado.

ModelViewer y Lottie funcionan correctamente solo con importar las respectivas librerías. No obstante para que particles.js tenga un buen rendimiento, vamos a controlar que solo se ejecuten cuando el usuario llega a la diapositiva adecuada.

let particles = undefined;
deck.on("slidechanged", (event) => {
  if (event.indexh === 4 && event.indexv === 1) {
    if (!particles) {
      particles = Particles.init({
        selector: ".background-particles",
        connectParticles: true,
        sizeVariations: 5,
        color: "#1c4f3e",
      });
    } else {
      particles.resumeAnimation();
    }
  } else {
    if (particles) {
      particles.pauseAnimation();
    }
  }
});

Finalizamos el script lanzando el método “initialize()” para iniciar la presentación.

deck.initialize();

En ésta ocasión no he manejado la “promise” que devuelve “initialize”. Pero te animo a que escales el código para que no se muestre nada en pantalla, hasta que se haya resuelto la promesa.

Crear presentaciones ya no volverá a ser una tarea tediosa. 

Eso ha sido todo por hoy, espero que el artículo te haya resultado interesante. Puedes dejar en los comentarios algún enlace a una presentación que hayas realizado, me haría mucha ilusión leerte.

Por loco que parezca, es posible hasta integrar un videojuego dentro de Reveal, por ejemplo creado con Phaser. Si te animas a probarlo, te dejo un enlace al artículo dedicado a esta otra magnífica librería.

Crear videojuegos con PhaserJs

Te dejo un listado a material adicional, por si quieres seguir aprendiendo sobre este y otros temas de desarrollo web.

Un saludo, y hasta pronto.

Deja un comentario