# Week 2

# Wat is p5.js?

p5.js (opens new window) is een JavaScript bibliotheek gebasseerd op de doelen van Processing (opens new window) (Pyhton bibliotheek) om programmeren toegankelijk te maken voor beginners, studenten, docenten, ontwerpers, kunstenaars …

p5.js is een soort schetsboek op het web en bevat een verzameling van objecten en methoden om graphics te genereren op deze schetsboek.

p5.js kan uitgebreid worden met extra bibliotheken (opens new window) en dus ook functionaliteiten om te intrageren met: het document object model, afbeeldingen, geluid, video …

p5.js is voornamelijk een wrapper bovenop de Canvas API (opens new window).

# Setup

Maak een folder aan met een naam die een indicatie geeft aan de webapplicatie, bijv.: p5_android_character. De folder bevat de volgende structuur:

  • p5_android_character (folder)
    • js (folder)
      • main.js (file)
    • index.html (file)

De HTML pagina ziet er als volgt uit:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Web Programming 1: Front-End Development | Associate Degree in Computer Programming</title>
    <link rel="stylesheet" href="css/main.css">
</head>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
    <script src="js/main.js"></script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

De p5.js bibliotheek wordt, in het HTML-bestand, gelinkt via het <script> element. In het src attribuut vermelden we het pad naar het JavaScript-bestand dat we wensen te linken. Dat kan een absoluut (lokaal) of relatief (via httpof https) pad zijn. We kiezen in dit geval voor een absoluut pad naar een online resource. p5.js wordt o.a. gehost in een CDN (Content Delivery Network).

We linken vervolgens een lokaal (relatief pad ten opzichte van het HTML-bestand) JavaScript-bestand main.js waarin we onze eigen code (Eng. custom code) zullen schrijven. Dit bestand bevat minstens twee ingebouwde functies uit p5.js, namelijk setup() (dit zijn de initiële settings van onze p5.js app) en draw (waarin we o.a. graphics zullen tekenen).

Het JavaScript-bestand bevat de volgende inhoud:

function setup() {
  noLoop();
}

function draw() {
  
}
1
2
3
4
5
6
7

De setup() (opens new window) methode wordt maar één keer aangeroepen wanneer het programma start. Het wordt voornamelijk gebruikt om omgevingseigenschappen in te stellen, zoals: schermgrootte, achtergrondkleur, éénmalig laden van media (afbeeldingen, audio, video, fonts …).

De draw() (opens new window) methode wordt direct uitgevoerd na de setup() methode. De draw() methode wordt continue uitgevoerd indien er geen noLoop() methode gedefinieerd is in de setup() of draw() methode. Indien noLoop() vermeld wordt in de setup() methode, dan zal de draw() éénmaal uitgevoerd worden. Kortom, voor animaties verwijder je de noLoop() methode.

# Onze eerste schets in p5.js

Na de voorgaande setup te doorlopen zullen we ons eerste p5.js schets maken. Deze schets is statisch (via de noLoop()) methode en bevat een reeks van graphics die “laag boven laag” getekend zullen worden cfr. de lagen in Adobe Photoshop CC of Adobe Illustrator CC.

In de setup() functie creëren we een nieuwe canvas (via de Canvas API) met de dimensie van 600 pixels breed en 600 pixels hoog. We voegen geen animatie toe door de noLoop() methode aan te spreken. Het achtergrondkleur van de canvas stellen we in op zwart via de methode background(0).

function setup() {
  createCanvas(400, 400);
  noLoop();
  background(0);
}

function draw() {
  rect(40, 40, width-80, height-80);
  line(40, 40, width-40, height-40);
  line(width-40, 40, 40, height-40);
  ellipse(40, 40, 40, 40);
  ellipse(width-40, 40, 40, 40);
  ellipse(width-40, height-40, 40, 40);
  ellipse(40, height-40, 40, 40);
  ellipse(width/2, height/2, 80, 80);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

In de draw() methode tekenen we de vormen die we wensen te generen binnen het <canvas> element. We tekenen eerst een rechthoek die start op positie (40, 40) met een breedte gelijke aan de breedte (width eigenschap) van de canvas vermindert met 80 en een hoogte gelijk aan de hoogte van de canvas (height eigenschap) vermindert met 80. We trekken twee spiegelende diagonale lijnen binnen dit vierkant. In elke hoek tekenen we een cirkel via de ellipse() methode. Tenslotte tekenen we ook een cirkel met een bepaalde dimensie in het midden van de rechthoek.

Resultaat:

foo

# Full width and height of the viewport

We breiden de mappenstructuur uit met een CSS-bestand waarin we opmaak kunnen coderen zodanig dat elke canvas element de volledige beschikbare breedte en hoogte gebruikt van het browservenster. De mannenstructuur ziet er nu als volgt uit:

  • hoofdmap (folder)
    • js (folder)
      • main.js (file)
    • css (folder)
      • main.css (file)
    • index.html (file)

De HTML pagina ziet er als volgt uit:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Web Programming 1: Front-End Development | Associate Degree in Computer Programming</title>
    <link rel="stylesheet" href="css/main.css">
</head>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
    <script src="js/main.js"></script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

De opmaak zorgt ervoor dat we de volledige breedte en hoogte in de webbrowser kunnen gebruiken voor onze toekomstige schetsboek. Als je niet de volledige breedte en hoogte nodig hebt dan verwijder je gewoon de canvas selector.

Het CSS-bestand bevat de volgende inhoud:

html, body {
    margin: 0;
    padding: 0;

    background: rgba(0, 0, 0, 1);
}
canvas {
    display: block;
    width: 100vw;
    height: 100vh;

    overflow: hidden;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

Het JavaScript-bestand main.js ziet er als volgt uit:

function setup() {
  createCanvas(windowWidth, windowHeight); // canvas bevat de volledige breedte en hoogte van de viewport
  background(0); // achtergrondkleur van de canvas is zwart
}

function draw() {
}
1
2
3
4
5
6
7

# Voorbeelden

# Enlarge and Shrinking

In dit voorbeeld maken we een bol met de volgende eigenschappen:

  • gecentreerd in het center van de canvas
  • de bol start met een dimensie van [0, 0] en groeit per frame, de dimensie wordt bijgehouden door de variabele r
  • indien de bol breeder wordt dan de canvas, dan wordt de groeirichting gewijzigd (groeien wordt krimpen)
  • de groeirichting wordt bepaald door de variabele direction
  • indien de bol kleiner wordt dan 0, dan wordt de groeirichting gewijzigd (krimpen wordt groeien)
  • de snelheid van groeien en krimpen wordt ingesteld via de variabele speed

De code:

/*
Variables
*/
let r = 0; // Size of the elippse
let speed = 10; // Speed of the animation for the ellipse
let direction = 1; // 1: enlarge, -1: shrink

function setup() {
    createCanvas(windowWidth, windowHeight); // canvas bevat de volledige breedte en hoogte van de viewport
    background(0); // achtergrondkleur van de canvas is zwart  
}

function draw() {
    background(0);
    ellipse(width/2, height/2, r, r); 
    if((r + speed) > width) {
        direction = -1;
    } else if ((r - speed) < 0) {
        direction = 1;
    }
    // speed += 2; // acceleration
    r += speed*direction;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# Rectangle Height Shrink Animated

In dit voorbeeld maken we een rechthoeken die van hoogte verminderen en opschuiven in de positieve x-richting. Defineer de variabelen:

  • x de x-positie van een rechthoek
  • w de breedte van een rechthoek
  • h de hoogte van de rechthoek variabel per frame

De code:

/*
Variables
*/
let x = 0; // position of the current rectangle
let w = 20; // width of a rectangle
let h = 0;

function setup() {
    createCanvas(windowWidth, windowHeight); // canvas bevat de volledige breedte en hoogte van de viewport
    background(0); // achtergrondkleur van de canvas is zwart 
    noStroke(); // no border

    h = height; // start height of the first rectangle
    rectMode(CENTER);
}

function draw() {
    //background(0);
    if(x > width) {
        // Stop generating rectangles
        background(255,0,0);
    } else {
        fill(random(0,255), random(0,255), random(0,255));
        rect(x, height/2, w, h); // draw a rectangle
        x += w;  
        h -= w/2;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# Square Animated

In dit voorbeeld maken we een rechthoeken (waarvan de dimensie afneemt totdat de breedte of hoogte van een volgende rechthoek kleiner wordt dan 0) met de volgende eigenschappen:

  • gecentreerd in het center van de canvas
  • een rechthoek start met een dimensie van [width, height] de volledige beschikbare breedte en hoogte van de canvas
  • de volgende rechthoeken (wordt per frame getekend) worden kleiner en kleiner, de dimensie wordt bijgehouden door de variabelen rW en rH
  • indien de volgende rechthoek een breedte of hoogte heeft die kleiner is dan 0, dan wordt de het tekenen van rechthoeken gestopt
  • op het einde van de animatie wordt een rode rechthoek getekend maar daarop de tekst “LOVE CODE”

De code:

/*
Variables
*/
let rW = 10;
let rH = 10;
let speed = 20;
let fontRegular;

function preload() {
    fontRegular = loadFont('assets/fonts/SourceCodePro-Regular.ttf');
}

function setup() {
    createCanvas(windowWidth, windowHeight); // canvas bevat de volledige breedte en hoogte van de viewport
    background(0); // achtergrondkleur van de canvas is zwart 
    //noStroke(); // no border

    rectMode(CENTER);

    rW = width;
    rH = height;
}

function draw() {
    if(rW > 0 && rH > 0) {        
        rect(width/2, height/2, rW, rH);
        rW -= speed;
        rH -= speed;
    } else {
        fill(255, 0, 0, 200);
        rect(width/2, height/2, width*0.8, height*0.25);
        textFont(fontRegular);
        textSize(height*0.1);
        textAlign(CENTER);
        strokeWeight(16);
        fill(255);
        text('LOVE CODE', width/2, height/2+(textDescent()));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

Opgelet

# Operating System Information

Maak een bestand operating_system_info.js aan in de reeds aangemaakt folder week-1. In deze applicatie lijsten we informatie op van ons besturingssysteem.

Opmerking

Voorbeeld output:

Homefolder:     /Users/drdynscript
Temp folder:    /var/folders/w1/c68647g15894_84z3mygb8sr0000gn/T
Hostname:       MacBook-Pro-van-Philippe.local
Platform:       darwin
Release:        18.7.0
Architecture:   x64
Total Memory:   8GB
Free Memory:    37.703125MB
Percent used:   99.54%
Uptime:         11722s

# Art

Maak een folder art aan met de mappenstructuur uit p5.js introductie. Deze applicatie genereert een verzameling van rechthoeken (zonder animatie) in grijstinten en op random posities.

Resultaat:

Art

# Bouncing circle

Maak een folder circle_bouncing aan met de mappenstructuur uit p5.js introductie. Teken een cirkel binnen deze methode startend op een random postie. Laat deze cirkel botsen tegen alle kanten van de canvas.

Opmerking

  • Definieer twee variabelen boven de setup(), namelijk let x = 0; en let y = 0;
  • Manipuleer de vorige variabelen met een nieuwe waarde waardoor de cirkel kan botsen tegen de randen
  • Gebruik het conditionele statement if…else if

Resultaat:

Bouncing circle

# Random walker

Maak een folder walker_random aan met de mappenstructuur uit p5.js introductie. Deze applicatie simuleert een wandelaar die bij iedere nieuwe frame beweegt (t.o.v. de vorige positie), hetzij (één van de 4 toestanden):

  • een aantal pixels naar boven
  • een aantal pixels naar beneden
  • een aantal pixels naar rechts
  • een aantal pixels naar links

De wandelaar vertrekt vanuit het midden van de canvas. De richting die de wandelaar maakt is één van de vier toestanden. De verplaatsing wordt weergegeven met een verbindingslijn tussen de huidige postie en de nieuwe positie.

Opmerking

  • Definieer twee variabelen boven de setup(), namelijk let x = 0; en let y = 0;
  • Manipuleer de vorige variabelen met een nieuwe waarde afhankelijk van de random keuze uit één van de 4 toestanden
  • De mate van verplaatsting varieert tussen 1 en 10 pixels
  • Gebruik het conditionele statement switch…case

Resultaat:

foo

# 50 shades

# Random colors

Maak een folder 50shades_random_colors aan met de mappenstructuur uit p5.js introductie. Deze applicatie genereert een grid van een aantal rechthoeken. De grid is schervullend. Bij elke nieuwe frame worden de rechthoeken hertekend met een random kleur per rechthoek.

Opmerking

  • Definieer twee variabelen boven de setup(), namelijk let cols = 10, rows = 10;
  • Bereken de hoogte en breedte van iedere rechthoek op basis van de variabelen rows en cols en de eigenschappen width en height
  • De grid wordt opgebouwd met een for-lus
  • Uitbreiding (excelleren): Definieer een functie generateRandomColor() waarmee we een random kleur kunnen genereren. Spreek deze aan bij elke volgende frame

Resultaat:

50 Shades of random colors

# Grey

Maak een folder 50shades_grey aan met de mappenstructuur uit p5.js introductie. Deze applicatie genereert een grid van een aantal rechthoeken. De grid is schervullend. Het tekenen wordt niet herhaald, vermeld hiervoor de functie noLoop() in de setup() functie. Alle rechthoeken bevatten een grijstint variërend van zwart (linksboven) tot wit (rechtsonder).

Opmerking

  • De grid wordt opgebouwd met een for-lus en een nested for-lus

Resultaat:

50 Shades of grey

# HSL colors

Maak een folder 50shades_hsl_colors aan met de mappenstructuur uit p5.js introductie. Deze applicatie genereert een grid van een aantal rechthoeken. De grid is schervullend. Bij elke nieuwe frame worden de rechthoeken hertekend met een een nieuwe kleur op basis van HSL (opens new window) (Hue, Saturation en Lightness). De Hue ligt bij iedere frame vast op een random waarde. Dat Saturation is afhankelijk van de kolommen, de Lightness is afhankelijk van de rijen.

Opmerking

  • Gebruik de functie colorMode() om de interpretatie van kleur te veranderen
  • De frame rate wordt ingesteld op 2 frames per seconde frameRate(2) in de setup() functie
  • Uitbreiding (excelleren): schrijf een functie waarmee je een HSB grid genereert met als argumenten xen y (startpositie van de grid), w (breedte van de grid), h (hoogte van de grid), hue (hue van de grid). Genereer 6 van deze grids door deze nieuwe functie aan te spreken, bijv.: functieNaam(0, 0, 100, 100, 35). Stop de frames!

Resultaat:

50 Shades HSL colors

# Repeating images

Maak een folder images_repeating aan met de mappenstructuur uit p5.js introductie. Deze applicatie genereert een aantal instanties van dezelfde afbeelding waarvan de grootte steeds verandert (kleiner worden na iedere iteratie). De afbeelding wordt geladen via de online service https://picsum.photos. Deze service genereert afbeeldingen on the fly waarin we o.a. de dimensies en randomness kunnen opgeven, bijv.: https://picsum.photos/1920/1080?random=1 (genereet een random afbeelding met een breedte van 1920 pixels en een hoogte van 1080 pixels).

Opmerking

  • Gebruik de preload() (opens new window) functie om afbeeldingen op voorhand in te laten
  • Gebruik de loadImage() (opens new window) functie om afbeeldingen in te laden, zodat de pixeldata kan bevraagd worden
  • Verplaats het tekenpunt van canvas naar het center via translate(width/2, height/2)
  • Teken de afbeeldingen met als tekenpunt het center van de afbeelding via imageMode(CENTER)
  • Gebruik een for-lus om een x aantal afbeeldingen te genereren. De x is instelbaar via een variabele amount

Resultaat:

foo

# Rotating repeating images

Maak een folder images_repeating_rotating aan met de mappenstructuur uit p5.js introductie. Deze applicatie genereert een aantal instanties van dezelfde afbeelding waarvan de grootte steeds verandert (kleiner worden na iedere iteratie en met een toenemende rotatiehoek). De afbeelding wordt geladen via de online service https://picsum.photos (laden op dezelfde manier dan de voorgaande oefening).

Opmerking

Resultaat:

foo
© 2025 Arteveldehogeschool Laatst bijgewerkt: 13/1/2025, 10:02:14