Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Quickstart: Building Interactive Graphics with p5.js

Tech 1

Project Initialization

p5.js can be integrated into a web environment via CDN for rapid prototyping or installed through package managers for production builds.

CDN Integration:

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"></script>

Package Manager Installation:

npm install p5
import { createCanvas, background } from 'p5';

Core Rendering Pipeline

All p5.js applications revolve around two primary lifecycle functions that establish the rendering context and manage continuous redraws.

  • setup(): Executes once at application launch. Used for initializing canvas dimensions, configuring scene properties, and loading initial assets.
  • draw(): Executes sequantially after setup() completes. Runs by default at 60 frames per second (FPS). Acts as the animation loop where frame-by-frame updates occur. Execution frequency can be adjusted using frameRate(n) or halted with noLoop().

Basic structure:

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  // Frame rendering logic here
}

Drawing Two-Dimensional Shapes

Coordinate systems in p5.js follow a top-left origin (0, 0). X increases to the right, Y increases downward.

Points and Lines

Points require explicit stroke thickness to become visible. Lines connect two coordinate pairs.

function setup() {
  createCanvas(300, 300);
}

function draw() {
  background(240);
  
  stroke(80);
  strokeWeight(4);
  point(150, 150);
  
  line(50, 50, 250, 250);
  line(250, 50, 50, 250);
}

Polygons and Quadrilaterals

Triangles require three vertex coordinates. Rectangles can be drawn with fixed corners or rounded edges.

function setup() {
  createCanvas(400, 300);
}

function draw() {
  background(255);
  
  noFill();
  stroke(100);
  triangle(100, 50, 200, 200, 50, 200);
  
  fill(200, 50, 50);
  rectMode(CENTER);
  rect(300, 150, 120, 80, 15); // Rounded rectangle
}

Circles and Ellipses

Circles use diameter, while ellipses accept separate width and height parameters.

function setup() {
  createCanvas(500, 300);
}

function draw() {
  background(245);
  
  strokeWeight(2);
  stroke(50, 50, 100);
  fill(180, 220, 150);
  
  circle(150, 150, 120);      // Diameter-based
  ellipse(350, 150, 200, 100); // Width & Height
}

Arcs and Curves

Arcs are defined by start and stop angles measured in radians. The drawing mode determines whether the arc is open, closed with a straight line, or filled as a pie slice.

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(20);
  translate(200, 200);
  
  stroke(255);
  strokeWeight(3);
  arc(0, 0, 250, 250, 0, HALF_PI, PIE);
  
  arc(150, -150, 200, 200, PI * 0.5, PI * 1.5, OPEN);
}

Visual Styling and Color Systems

Rendering attributes apply globally until explicitly changed. Use push() and pop() to isolate style changes.

Color Modes

p5.js supports multiple color representations. Global state must be set before applying colors.

function setup() {
  createCanvas(400, 300);
  
  // Switch to HSB (Hue, Saturation, Brightness)
  colorMode(HSB, 360, 100, 100, 1);
  
  background(200, 20, 90); // Blue sky base
  
  // Draw shapes with different color modes applied locally
  push();
    colorMode(RGB, 255);
    fill(255, 0, 0, 0.7);
    noStroke();
    rect(50, 50, 150, 150);
  pop();
  
  // Grayscale mode (default)
  fill(180);
  square(250, 100, 100);
}

Stroke and Fill Controls

  • fill(r, g, b, alpha): Sets interior polygon color. Defaults to white if omitted.
  • stroke(r, g, b, alpha): Defines outline color. Defaults to black.
  • noFill() / noStroke(): Disables interior filling or outlining entire.
  • strokeWeight(n): Adjusts line thickness and point size.
function setup() {
  createCanvas(300, 300);
}

function draw() {
  background(250);
  
  push();
    fill(60, 100, 200, 0.6);
    stroke(20);
    strokeWeight(2);
    circle(100, 150, 100);
  pop();
  
  push();
    noFill();
    stroke(200, 50, 50);
    strokeWeight(6);
    quad(180, 80, 280, 80, 250, 220, 150, 220);
  pop();
}

Typography Handling

Text placement anchors at the baseline's left edge. Bounding boxes can restrict overflow.

function setup() {
  createCanvas(400, 300);
  textFont('Courier');
}

function draw() {
  background(240);
  textAlign(CENTER, CENTER);
  textSize(32);
  fill(30);
  
  text("Rendered Text Block", 200, 100);
  
  // Constraining text within a virtual box
  textAlign(LEFT, TOP);
  textSize(16);
  fill(100);
  text("Wrapped content automatically adjusts based on x2 boundaries.", 40, 180, 200, 80);
}

Asset Management

External media like images or audio must load asynchronously to prevent blocking the render thread.

let sceneAsset;
let assetLoaded = false;

function preload() {
  sceneAsset = loadImage('assets/background.png');
}

function setup() {
  createCanvas(600, 400);
  assetLoaded = true;
}

function draw() {
  if (!assetLoaded) return;
  
  background(240);
  image(sceneAsset, 0, 0, width, height);
  
  fill(0);
  textSize(14);
  text(`Image Dimensions: ${sceneAsset.width}x${sceneAsset.height}`, 20, height - 30);
}

State-Driven Interactivity and Animation

Continuous motion relies on updating positional variables each frame and redrawing the canvas context.

Event Detection

Global boolean flags track input state during the render loop.

function setup() {
  createCanvas(500, 300);
}

function draw() {
  // Dynamic background based on interaction
  if (mouseIsPressed) {
    background(40, 60, 120);
  } else {
    background(240);
  }
  
  if (keyIsPressed) {
    fill(200, 50, 50);
  } else {
    fill(50);
  }
  
  noStroke();
  ellipse(width / 2, height / 2, 80);
}

Coordinate Tracking and Motion

Mouse position (mouseX, mouseY) can drive element placement. To prevent visual artifacts during movement, clear the previous frame before redrawing.

let targetPos = { x: 0, y: 0 };
let currentPos = { x: 0, y: 0 };

function setup() {
  createCanvas(600, 400);
  targetPos.x = mouseX;
  targetPos.y = mouseY;
}

function draw() {
  // Clear screen for next frame
  background(255);
  
  // Update tracking targets
  targetPos.x = mouseX;
  targetPos.y = mouseY;
  
  // Smooth interpolation toward target
  lerpVal = 0.08;
  currentPos.x = lerp(currentPos.x, targetPos.x, lerpVal);
  currentPos.y = lerp(currentPos.y, targetPos.y, lerpVal);
  
  // Render following element
  fill(80, 120, 200, 150);
  stroke(20);
  strokeWeight(1);
  circle(currentPos.x, currentPos.y, 60);
  
  // Draw trajectory trail
  noFill();
  stroke(200, 100);
  arc(currentPos.x - 40, currentPos.y, 100, 100, -HALF_PI, 0);
}

By leveraging these core primitives and lifecycle controls, developers can construct complex generative visuals, data-driven charts, and interactive installations without leaving the browser environment.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.