Op Art Tiles

Op Art Tiles

Here is another short program that uses recursion to draw on the canvas.

Our HTML file for this program is very simple:

<html>
  <head>
  </head>
  <body>
    <canvas id='canvas'></canvas>
    <script src="tiles.js"></script>
  </body>
</html>

The code for the program is only a little bit more complex:

class Tiles
{
  constructor()
  {
    this.canvas = document.querySelector( 'canvas' );
    this.context = canvas.getContext( '2d' );
    this.wide = 0 | window.innerWidth / 21;
    this.high = 0 | window.innerHeight / 21;
    this.canvas.width = window.innerWidth;
    this.canvas.height = window.innerHeight;
    this.context.lineWidth = 2;
  }

  tiles()
  {
    for( let x = 0; x < 20; x++ )
    {
      for( let y = 0; y < 20; y++ )
      {
        this.tile( x * this.wide, y * this.high, this.wide, this.high );
      }
    }
  }

  paint( x, y, w, h )
  {
    this.context.beginPath();
    this.context.fillStyle = '#' + Math.floor( Math.random() * 16777215 ).toString( 16 );
    this.context.fillRect( x, y, w, h );
    this.context.rect( x, y, w, h );
    this.context.stroke();
  }

  tile( x, y, w, h )
  {
    this.paint( x, y, w, h );
    let shift_x = 3 | Math.random() * 5;
    let shift_y = 3 | Math.random() * 5;
    let shift_w = 1 | Math.random() * 5;
    let shift_h = 1 | Math.random() * 5;
    w -= Math.max( shift_w * 2, shift_x * 2 );
    h -= Math.max( shift_h * 2, shift_y * 2 );
    if( w > 0 && h > 0 )
    {
      this.tile( x + shift_x, y + shift_y, w, h );
    }
  }
}

let t = new Tiles();
t.tiles();

 

The constructor for the Tiles class should look somewhat familiar. We get the canvas context so we can draw things. We make the canvas take up the whole window. We set a couple variable (wide and high) to be 1/21st of the size of the window, and we use our bitwise OR trick to convert the floating point number to an integer by throwing away everything after the decimal point.

The tiles() method draws a grid of 20 by 20 tiles by calling the tile() method for each one. Because we divided by 21 in the constructor, we don't draw past the ends of the window.

The paint() method should also look familiar by now. We set the fillStyle to a random color, call fillRect() to make a rectangle of that color, call rect() to outline it in black, and surround all of that with beginPath() and stroke(), as we have before.

Let's look at the tricky code for picking a random color. Our colors are made up of 8 bits for red, green, and blue. That's a total of 24 bits. Two to the 24th power is 16,777,216 (and since we count from zero, we subtract one). Multiplying by Math.random() gives us a random number between 0 and 16,777,215. We use Math.floor() to convert this number to an integer (we could instead have used our bitwise OR trick here). In HTML, colors are specified as a pound sign followed by a 24 bit number, expressed in base 16 (hexadecimal). We use the toString(16) method to convert the number into hexadecimal, and then we stick a pound sign in front to make it an HTML color.

The tile() method is actually simpler than it appears at first. It calls paint to color in a rectangle. Then it picks some random numbers to use to pick a new rectangle's x, y, w, and h values. If the values haven't shrunk to zero or less, it calls itself (recursion) to draw the smaller rectangle inside this one, and so on, until the width or height are too small.

All that remains is to create an instance of the Tiles class, and then call the tiles() method on that, and we get a pretty picture.

You can play with the program here. Every time you refresh the page, you get a new painting.