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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ npm -g install ionic
$ npm -g install ionic
$ npm -g install ionic

Create base app structure

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ ionic start working-with-p5js blank --type angular
$ cd working-with-p5js
ionicstartworkingwithp5jsblanktypeangular cd working-with-p5js
$ ionic start working-with-p5js blank --type angular
$ cd working-with-p5js

Add p5.js to the ionic app

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ npm install --save-dev p5
$ npm install --save-dev p5
$ npm install --save-dev p5

Test your base app

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ ionic serve
$ ionic serve
$ ionic serve

Starting with p5.js

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

Modify home.page.html

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<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>
<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>
<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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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);
}
}
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); } }
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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');
}
}
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'); } }
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