P5js Multi-Instancing

Making a generative art gallery

P5js Multi-Instancing

I've been slowly remaking my personal website. I keep toying with the idea of making a full SPA but never really get round to investing that much time into it. My site is a simple static html page served serverless via s3 & cloudfront. My own personal playground to carve out a small section of the internet just for me. It's sole purpose is to display what I'm about and things that interest me.

For years I've been following the amazing Dan Shiffman of The Coding Train and his amazing videos in processing and p5js, whilst playing around making generative art & interactive sketches of my own. Recently I saw an amazing talk by Tim Holman about Generative Art in which he displayed a little gallery at the end which inspired me to create my own!

IBGenerativeGallery.gif

So now I had an idea, but up until this point I had never used more than one p5js sketch in a single page. Being aware that it could be instanced didn't really make it any easier to load the p5js library once, but then have it used by many different sketches at the same time within the one web page. Thankfully the documentation for p5js is pretty great and there is an example of running a p5js sketch in an instance even specifying the container element it should load into on the page.

Armed with this knowledge I created a simple helper class that would allow for copying the existing sketches code and reformatting into single object model that would provide the base properties as well as helper computed properties allowing for p5 to be store against the class instance for use later as a self reference.

// helper class for instancing p5 sketches
class Sketch {
  constructor({
    p,
    name,
    vars,
    sketch,
    reset,
    size,
    functions
  }) {
    this.p = p
    this.name = name
    this.vars = vars
    this.sketch = sketch
    this._reset = reset
    this._size = size || {
      width: 300,
      height: 300
    }
    this.sketch = this.sketch.bind(this)

    if (functions) {
      // add custom functions to class instance
      Object.keys(functions).forEach(fn => this[fn] = functions[fn])
    }

    // ensure binding for class functions
    Object.keys(this).forEach(prop => {
      if (typeof this[prop] === 'function') {
        this[prop] = this[prop].bind(this)
      }
    })
  }

  get p5() {
    return this.p
  }

  set p5(p) {
    this.p = p
    this.p.windowResized = () => {
      this.p.resizeCanvas(this.size.width, this.size.height)
    }
  }

  get size() {
    return {
      width: window.innerWidth >= this._size.width + 60 ? this._size.width : window.innerWidth * 0.6,
      height: window.innerHeight >= this._size.height + 60 ? this._size.height : window.innerHeight * 0.6
    }
  }

  reset() {
    if (this._reset && typeof this._reset === 'function') {
      this._reset(this)
    } else {
      this.p.setup()
    }
  }
}

This class allows for easily generating several sketches at once in a single file and have them follow the architecture. They all have built in responsiveness and point to their own walled garden version of p5js!