¿Cómo crear un efecto de onda con Canvas y JavaScript?

- Andrés Cruz

In english
¿Cómo crear un efecto de onda con Canvas y JavaScript?

Ver ejemplo

En esta entrada veremos cómo crear una onda como la siguiente:

 

Para esto usaremos el elemento Canvas provista por HTML5 y la función llamada Window.requestAnimationFrame() introducida en una entrega anterior llamada: EL SECRETO DE LAS ANIMACIONES EN JAVASCRIPT (REQUESTANIMATIONFRAME()); recordando un poco el uso de la función Window.requestAnimationFrame(), permite animar figuras dibujadas en un elemento Canvas; en otras palabras:

Con la función requestAnimationFrame() se obtienen transiciones o cambios suaves a través de una API que se encuentra optimizado para trabajar con el Canvas.

Para más información, vea el enlace anterior.

Construyendo la onda (JavaScript)

El JavaScript es en realidad corto y sencillo; pero a su vez puede resultar algo enredado debido a las operaciones matemáticas de sumas y divisiones pero trataré de explicarlo de la manera más sencilla.

Antes de mostrar el código es necesario recordar la función seno o coseno que seguramente viste en el colegio y universidad; estas funciones son como olas que vienen y van:

función Coseno

Imagen obtenida de: Coseno.

La función coseno o seno nos viene de maravilla para realizar este experimento y esto es debido a su efecto de ola u onda que poseen; si no recuerdas que son estas funciones en Internet conseguirás bastante material al respecto.

Volviendo a la aplicación de estas funciones en JavaScript tenemos que:

  • Math.cos(n) es empleada para aplicar el coseno.
  • Math.sin(n) es empleada para aplicar el seno.

Finalmente les presento el código JavaScript completo:

    var c = document.getElementById('canv');
    var $ = c.getContext('2d');

    var w = c.width = window.innerWidth;
    var h = c.height = window.innerHeight;

    var draw = function(t) {
      $.lineWidth = 1;
      $.fillStyle = 'rgb(0, 0, 0)';
      $.fillRect(0, 0, w, h);

      for (var i = -60; i < 60; i += 1) {
        $.strokeStyle = 'rgb(255, 255, 255)';
        $.beginPath();
        $.moveTo(0, h / 2);
        for (var j = 0; j < w; j += 10) {
          $.lineTo(10 * Math.cos(i) +
            j + (0.008 * j * j),
            Math.floor(h / 2 + j / 2 *
              Math.cos(j / 50 - t / 50 - i / 118) +
              (i * 0.9) * Math.cos(j / 25 - (i + t) / 65)));
        };
        $.stroke();
      }
    }
    var t = 0;

    window.addEventListener('resize', function() {
      c.width = w = window.innerWidth;
      c.height = h = window.innerHeight;
    }, false);

    var run = function() {
      window.requestAnimationFrame(run);
      t += 5;
      draw(t);
    };

    run();

Como podrás imaginar, el HTML consisten en una simple etiqueta Canvas.

Algunas consideraciones sobre el JavaScript anterior

Primero Inicializamos algunas variables globales para obtener acceso al elemento Canvas, su contexto y dimensiones:

var c = document.getElementById('canv');    var $ = c.getContext('2d');    var w = c.width = window.innerWidth;    var h = c.height = window.innerHeight;

Dentro de la función draw()

Definimos algunos estilos a las líneas que vamos a pintar:

$.lineWidth = 1;
$.fillStyle = 'rgb(0, 0, 0)';
$.fillRect(0, 0, w, h);
$.strokeStyle = 'rgb(255, 255, 255)';

Este primer for permite dibujar un conjunto de líneas en paralelo; al variar la cota inferior y superior podemos crear ondas más o menos anchas; además este for se encarga de inicializar componentes necesarios para pintar líneas.

    for (var i = -60; i < 60; i += 1) {
              $.beginPath();
              $.moveTo(0, h / 2);
                       /*For anidado*/
              $.stroke();
            }

En otras palabras, si este for no estuviera, nuestra onda se vería como un látigo:

Onda látigo

El siguiente código es un for anidado que pinta w líneas por vez; en donde w es el ancho de la pantalla:

    for (var j = 0; j < w; j += 10) {
      $.lineTo(10 * Math.cos(i) +
        j + (0.008 * j * j),
        Math.floor(h / 2 + j / 2 *
          Math.cos(j / 50 - t / 50 - i / 118) +
          (i * 0.9) * Math.cos(j / 25 - (i + t) / 65)));
    };

Como podrás ver, empleamos múltiples funciones cosenos (Math.cos) para crear un variado efecto onda (y no tan constante como el coseno).

Las divisiones y multiplicaciones por números bajos es para mantener los valores lo más "constantes" posibles y que la onda no vaya a variar de tamaño radicalmente a medida que los valores de los fors (var j y var i) aumenten.

Para tener una animación variada, cada vez que se ejecuta recursivamente la función draw() a través de la función window.requestAnimationFrame(run); se varía el valor de la variable t para tal fin.

Finalmente creamos la función run() la cual es invocada al cargar la página web.

var run = function() {
      window.requestAnimationFrame(run);
      t += 5;
     draw(t);
};

Este experimento fué tomado de CodePen: Wind y modificado a gusto.

Ver ejemplo

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.