How to create a wave effect with Canvas and JavaScript?

- Andrés Cruz

En español
How to create a wave effect with Canvas and JavaScript?

Example

In this post we will see how to create a wave like the following:

 

For this we will use the Canvas element provided by HTML5 and the function called Window.requestAnimationFrame() introduced in a previous installment called: THE SECRET OF ANIMATIONS IN JAVASCRIPT (REQUESTANIMATIONFRAME()); Recording a bit the use of the Window.requestAnimationFrame() function, it allows you to animate figures drawn on a Canvas element; in other words:

With the requestAnimationFrame() function, smooth transitions or changes are obtained through an API that is optimized to work with Canvas.

For more information, see the link above.

Building the Wave (JavaScript)

The JavaScript is actually short and simple; but at the same time it can be somewhat entangled due to the mathematical operations of addition and division but I will try to explain it in the simplest way.

Before showing the code, it is necessary to remember the sine or cosine function that you probably saw at school and university; these functions are like waves that come and go:

función Coseno

Image obtained from: Coseno.

The cosine or sine function is wonderful for us to carry out this experiment and this is due to its wave or wave effect that they have; If you do not remember what these functions are on the Internet, you will get a lot of material about it.

Returning to the application of these functions in JavaScript we have that:

  • Math.cos(n) is used to apply the cosine.
  • Math.sin(n) It is used to apply the breast.

Finally I present the complete JavaScript code:

    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();

As you can imagine, HTML consists of a simple Canvas tag.

Some considerations about the above JavaScript

First we initialize some global variables to get access to the Canvas element, its context and dimensions:

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

Inside draw() function

We define some styles to the lines that we are going to paint:

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

This first for allows you to draw a set of lines in parallel; by varying the lower and upper bounds we can create more or less wide waves; In addition, this for is in charge of initializing the necessary components to paint lines.

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

In other words, if this for were not there, our waveform would look like a whip:

Onda látigo

The following code is a nested for that prints w lines at a time; where w is the width of the screen:

    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)));
    };

As you can see, we use multiple cosine functions (Math.cos) to create a varied ripple effect (and not as constant as cosine).

The divisions and multiplications by low numbers are to keep the values as "constant" as possible so that the wave will not vary in size radically as the values of the fors (var j and var i) increase.

To have a varied animation, each time the draw() function is executed recursively through the window.requestAnimationFrame(run); the value of the variable t is varied for this purpose.

Finally we create the function run() which is called when loading the web page.

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

This experiment was taken from CodePen: Wind and modified to taste.

Example

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.