Hi, I’m Rachel Smith, you may remember me from such previous pens as these Canvas particles, It Depends, this pixel grid or the animated rainbow spew cartoon.

I get a lot of wonderful feedback on my pens, which I truly appreciate. Sometimes people write to me to tell me that they also want to create animations like this, but they can’t design or imagine what they want to code.

Here’s the thing... most of the time, neither can I.

The final result in the various generative pens I’ve created rarely resembles my initial idea or momentary inspiration. I actually work through an iterative process to create something I’m happy with, and I want to share that process with you today.

THE PROCESS

Start with a small piece of code
To create a pen I start with a building block of some kind, in WebGL, canvas, SVG or a HTML element. This might be:
a shape, an image, a path, or an element

The rest of the process is taking the time to figure out what I want to:
Parameterize
find what parts of the code can be turned in to parameters/variables.
Randomize
determine what parameters can be randomized to create an interesting visual effect.
Tween
given I have controllable parameters, which ones can I tween or animate?
Iterate through
what can I iterate through to make the animation more visually interesting?


An example: fun with an SVG curve

Consider the code to create a cubic bezier SVG path:

  <path d="M100,250 c0,-150 300,-150 300,0" />

The string assigned to the d attribute here describes the coordinates of the four points that control a cubic bezier curve.

The four points of the curve (cheers Wikipedia for the illustration)

Parameterize: Using JavaScript, I’ll take the d string and substitute these values for parameters, so they can be controlled.

  // this code dynamically generates a <path> element
// and assigns the string to the d attribute.
const path = document.createElementNS('http://www.w3.org/2000/svg', ‘path');
// here I'm using variables in place of values to 
// control the points of the curve
let d = `M${x0},${y0} c${x1},${y1} ${x2},${y2} ${x3},${y3}`;
path.setAttribute('d', d);


Note: the JavaScript syntax being used in this post is es2015, which is not yet fully supported in browsers. The example pens below have Babel transpiling set on, so you can check the compiled output if you're trying to work in es5.

Awesome, now I have the basis of my path code I’ll create a class that will control each of my curves. Usually, if I’m going to create a number of the same type of shape/object I’ll create a JavaScript class to control the properties and methods of each of those objects.

  class Blob {
  constructor(x, y, width, height) {
    // this constructor sets the values for the points
    // in the curve
    this.x0 = x;
    this.x1 = width/3;
    this.x2 = width/3*2;
    this.x3 = width;
    this.y0 = y;
    this.y1 = height;
    this.pathEl = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    this.pathEl.setAttribute('fill', color);
  }

  // this is the method that will update the d
  // attribute on the path
  updatePath() {
    this.pathEl.setAttribute('d', `M${this.x0},${this.y0} c${this.x1},${this.y1} ${this.x2},${this.y1} ${this.x3},0`);
  }
}

Randomize: the next step in the process is to think about what I can randomize.
My initial thoughts are: given I have control over the width and height of any curve, maybe I could randomize those values? Let's see what that constructor looks like.

  constructor(x, y, maxHeight) {
    // this constructor sets the values for the points
    // in the curve
    this.x0 = x;
    // random width
    this.x1 = Math.random()*40;
    this.x2 = this.x1 + Math.random()*40;
    this.x3 = this.x2 + Math.random()*40;
    this.y0 = y;
    // random height
    this.y1 = -20 + maxHeight*Math.random();
    this.pathEl = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    this.pathEl.setAttribute('fill', color);
  }

Because I’m using Math.random() when creating the x2, x3, y1, values. My curves will have varying widths and height.

Thanks to my Blob class, I now have the ability to generate curves of random sizes at given positions. I’m going to generate a line of them at the bottom of the window.

  // this function will create a row of curves at the
// bottom of the browser window
const createBlobRow = () => {
  var y = window.innerHeight;
  for (var x = 0; x < window.innerWidth;) {
    var blob = new Blob(x, y, window.innerHeight*0.5);
    blobs.push(blob);
    svg.appendChild(blob.pathEl);
    // increase x by last blob width
    x += blob.x3;
    blob.updatePath();
  }
}

That’s something. It’s not super exciting yet, but it’s something we can work with.

Tweening and animating: my favourite part of the whole shebang! I’m staring at these curves, with their randomized heights. What if I made the height of each of these curves animate up and down?

  animate() {
    var _this = this;
    var time = 0.3 + Math.random()*1.2;
    // tween up to the target y
    TweenLite.to(_this, time, {
      y1: _this.yTarget,
      ease: Power2.easeInOut,
      onUpdate: () => _this.updatePath(),
      // tween back down to 0
      onComplete: () => TweenLite.to(_this, time, {
        y1: 0,
        onUpdate: () => _this.updatePath(),
        // restart the animate function
        onComplete: () => _this.animate()
      })
    });
  }

I’m adding an animation method to my Blob class, which will tween the height of the curve to a randomized target height. I want the curve to continue animating up and down continuously, so I’ll make the method call itself once the tween has completed. You may notice, that I’ve also chosen to randomize the duration of these tweens. Random can be used in many ways such as timing, shape and color to bring visual interest to an animation. If you’re feeling like your pen could use a little somethin’ and you can’t put your finger on what it is, try randomizing some stuff.

Sweet, this is starting to look pretty cool! But I’m not really feeling the black and white theme. It's time to add some color.

Iterate through: Now there are any number of properties you could choose to iterate through, like shapes or even emoji. But my favourite thing to iterate through is arrays of color.

I’ve never been someone who is good at putting colour schemes together by hand. Thankfully I’ll never need to when I have color scheme designing tools like coolors.co, and colour scheme libraries like colourlovers.com The color scheme for this pen, I actually found on pinterest after googling "neon rainbow color scheme". I'm particularly fond of rainbow schemes 💁🏻🌈.

I take my colors and put them in to an array.

  const colors = ['#C501E1', '#9A26F8', '#6564FE', '#2B97FA', '#02C4E7', '#16E6CC', '#2EF9A0', '#C6E501', '#E7C501', '#FF6A63', '#F82D98', '#E830CE'];

And now as I create each blob, I'll iterate through the colors array and assign each blob a new color.

  const createBlobRow = (maxHeight, colorOffset) => {
  var y = window.innerHeight;
  var c = colorOffset;
  for (var x = 0; x < window.innerWidth;) {
    // assign the color
    var color = colors[c]
    var blob = new Blob(x, y, maxHeight, color);
    blobs.push(blob);
    svg.appendChild(blob.pathEl);
    x += blob.x3;
    // move through the color array
    // reset to start if we've reached 
    // the end
    c++;
    if (c === colors.length) c = 0;

    blob.animate();
  }
}

I'll also change my background color to black because I really want my neons to pop. Let's see the result:

Funnnnn!!!!!

The way I've been explaining this to you, makes it almost seem like a linear process. But the truth is although I often use all of these steps at some point when I'm making a new pen, I don't follow any strict order. I often double back and mess with shapes, colours and timing, motion and timing (I spend a LOT of time messing around with timing). I'll play with variables and generate different effects until I end up with something that is fun to stare at.

Eventually after some messing around with the blobs above, I decided to layer the blobs and also add some contrasting animating lines in the background, and this was the end result:

So hopefully, you've found this breakdown of my process helpful, and you'll feel encouraged to experiment with your own animated effects.

And remember, don't stress about being able to design or picture a final effect in your mind. In my opinion, the learning and experimentation along the way is more important than the final result. As long as you're trying new things and having fun with it you're bound to end up with something fun to look at in the end :)


5,624 2 70