Poly Maker

See the experiment

Synopsis

When I designed the site I designed some low poly shapes for the blog. Obviously for the design I did them by hand, but I knew I wanted them to be generative in the final version. So when I was at a loose end on a trip to Mountain View (visiting the Google Mothership, for the lolz) I took a day out to create the requisite chunk of code.

I wrote it as a prototype, you can totally break it. Do I look like I mind? I do not.

Building the shape

We start with four points needed to build a cubic bezier curve:

Essentially we can now interpolate between the points to get to a curve. Well, I say curve, but it really depends on how many steps we use in the interpolation. In my case I think I default to about 10 steps so you can see straight lines in my “curve”.

Now that we have a curve we can shoot out lines perpendicular to the curve at each of the interpolation points.

Along those lines we can place some points. The green ones are our shape’s contour points, the blue ones are inside the shape.

Next let’s add a bit of jitter to our points so it’s not as uniform:

Now comes the interesting bit where we have to use Delauney Triangulation to connect the points into triangles. I can’t tell you how much I didn’t want to code it up, so I won’t. Instead I will just point out that there’s a perfectly decent library called poly2tri that has a JavaScript port. Wheel reinvention: avoided.

Once we run that against our points we get a bunch o’ triangles:

Coloring

Next up: coloring the shape. All I did was create a box with a gradient: color1 -> color2 -> color1 in the X axis, white -> black in the Y axis. That gives us a block like this:

Then it was just a case of looking up the color for the triangle, which I did by figuring out the coordinates of the triangle’s center and mapping that to our block.

Now query the block at that pixel and we have our triangle’s color. It gives a lit look. I’m such a cheat. Do I look like I care? I do not.

lookUpColor_: function(point1, point2, point3) {

  // colorData_ is the image data for the color block
  var data = this.colorData_.data;
  var cx = ((point1.x + point2.x + point3.x) / 3);
  var cy = ((point1.y + point2.y + point3.y) / 3);
  var x = Math.floor(cx);
  var y = Math.floor(cy);

  // look up the pixel color
  var pixel = (y * this.colorData_.width + x) * 4;

  // cast to hex
  var red = data[pixel].toString(16);
  var green = data[pixel + 1].toString(16);
  var blue = data[pixel + 2].toString(16);

  // pad out if we need to
  if (red.length < 2)
    red = '0' + red;

  if (green.length < 2)
    green = '0' + green;

  if (blue.length < 2)
    blue = '0' + blue;

  return '#' + red + green + blue;
}

Now when we apply that to all our triangles we get our colored shape:

Adding a shadow

This was just a little touch I wanted to add to the whole process, and it’s rather simple thanks to other peoples’ work. For this I basically create a circle with a gradient in its center (from black to transparent), which looks like this:

Then I applied a scale transform to squish it down to an ellipse:

That looks close, but it’s a bit sharp and it’s in need of a blur, not something natively available to canvas contexts. But thanks to Mario Klingemann there is a freely available block of code to apply blurs! So I chucked that on.

Finished product

After that it was just a bit of positioning and using Soledad Penadés’s Tween.js library to do some easing of the triangles into position!

And we’re done!