Ionic | Working with p5.js

Introduction

p5.js is a JavaScript library for creative coding, with a focus on making coding accessible and inclusive for artists, designers, educators, beginners, and anyone else.

In this Post, you will learn how to create an ionic app using p5.js to create an amazing demo of the Lissajous Curve (de/en).

If you want to learn more about this amazing graphs, take a look at some examples at codepen.io. Some amazing examples are here, here and here.

As always, you will find the final project on Github.

Preparation

You will need to install Node.Js, Ionic and p5.js.

First step is, to install Node.Js. I will refer to the installation pages on Node JS.

After installing Node.js, you will also have the Node Package manager, npm. We will use this tool to install the other requirements.

Install Ionic

$ npm -g install ionic

Create base app structure

$ ionic start working-with-p5js blank --type angular
$ cd working-with-p5js

Add p5.js to the ionic app

$ npm install --save-dev p5

Test your base app

$ ionic serve

Starting with p5.js

Add the base components of p5.js to our app.

Modify home.page.html

<ion-header>
	<ion-toolbar>
		<ion-title>Working with p5.js</ion-title>
	</ion-toolbar>
</ion-header>

<ion-content>
	<div id="canvasContainer" class="canvas-container"></div>
</ion-content>

Modify home.page.ts

import { Component, OnInit, ElementRef } from '@angular/core';

import * as p5 from 'p5';

@Component({
	selector: 'app-home',
	templateUrl: 'home.page.html',
	styleUrls: [ 'home.page.scss' ],
})
export class HomePage implements OnInit {

  curve: any;
  canvasSizeX = 200;
  canvasSizeY = 200;

  constructor(private el: ElementRef) { }

  ngOnInit() {
    const p5obj = new p5(p => {
      p.setup = () => { this.setup(p); };
      p.draw = () => { this.draw(p); };
    }, this.el.nativeElement);
  }

  setup(p) {
    const c = document.querySelector('#canvasContainer');
    p
      .createCanvas(this.canvasSizeX, this.canvasSizeY)
      .parent(c);
  }

  draw(p) {
    p.background(220);
  }
}

And the result ist your frist p5.js graphic:

Next, we will grab an example from p5.js: form-regular-polygon

Modify home.page.ts

We modify the draw function and add a required polygon function.

import { Component, OnInit, ElementRef } from '@angular/core';

import * as p5 from 'p5';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {

  curve: any;
  canvasSizeX = 720;
  canvasSizeY = 400;

  private ID = 'HomePage';
  log(func, line = '') {
    console.log(this.ID + '::' + func + '|' + line);
  }

  constructor(
    private el: ElementRef
  ) {
    this.log('constructor');
  }

  ngOnInit() {
    this.log('ngOnInit');

    const p5obj = new p5(p => {
      p.setup = () => {
        this.setup(p);
      };

      p.draw = () => {
        this.draw(p);
      };
    }, this.el.nativeElement);
  }

  setup(p) {
    this.log('setup');

    const c = document.querySelector('#canvasContainer');
    p
      .createCanvas(this.canvasSizeX, this.canvasSizeY)
      .parent(c);
  }

  polygon(p, x, y, radius, npoints, color) {
    const angle = p.TWO_PI / npoints;
    p.beginShape();

    p.fill(color);
    for (let a = 0; a < p.TWO_PI; a += angle) {
      const sx = x + Math.cos(a) * radius;
      const sy = y + Math.sin(a) * radius;
      p.vertex(sx, sy);
    }
    p.endShape(p.CLOSE);
  }

  draw_figure(p, scaleX, scaleY, divisor, radius, npoints, color) {
    p.push();
    p.translate(this.canvasSizeX * scaleX, this.canvasSizeY * scaleY);
    p.rotate(p.frameCount / divisor);
    this.polygon(p, 0, 0, radius, npoints, color);
    p.pop();
  }

  draw(p) {
    p.
      background('white');

    this.draw_figure(p, 0.2, 0.5, 200.0, 82, 3, 'red');
    this.draw_figure(p, 0.5, 0.5, 50.0, 80, 20, 'blue');
    this.draw_figure(p, 0.8, 0.5, -100.0, 70, 7, 'green');
  }
}

And we get a nice litte animation:

Additional Resources and Reading

Websites