Week 10: Media, Drawing & Animation
To Do This Week
Explore the front-end modules this week and next. By the end of Week 11 you will have tried five techniques you can combine in your two Front-End Module Projects.
Keep a running list of combination ideas as you go.
Front-End Module Projects (10% + 10%)
Complete two independent projects after exploring the course’s front-end modules. Each project must combine at least two of the following:
- HTML5 Audio or Video
- Canvas or SVG interaction or animation
- p5.js experimentation
- An API using
fetch(), for example a weather app - Basic HTML5 game using Canvas techniques
The projects should demonstrate creative intent rather than merely showing that a feature works. These are small ways to play with techniques that can lead toward your final project.
Minimum Requirements for Each Project
- At least two front-end modules used in combination
- An original concept, visual approach, or interactive purpose
- Functional, tested JavaScript
- A responsive and readable interface
- A project statement and numbered logic steps
- Complete documentation of AI use
Using AI
You may use AI to research and test out your ideas. What I will be covering in class is just a basic understanding of the different techniques. You will have to do some research and experimentation on your own. Once you are reading to build your projects, use the JS Mentor Metapromptto build logic steps and write the script with JS syntax. Document what AI contributed and how you evaluated, changed, and extended the generated material. Include chat URLs in your script comments.
Monday: Audio/Video, SVG & Canvas Drawing
Audio and video: you control
The <audio> and <video> hold media, like a recorded sound, a song, or a film clip. JavaScript drives playback: play(), pause(), currentTime, volume, loop. It also listens for events like ended, timeupdate, or canplay.
Use it when the content is recorded media and the interaction is about when and how it plays. Examples: a custom video player, a sound that triggers on click, a story that moves to the next clip when one ends, ambient audio that fades as the user scrolls.
SVG: interactive vector graphics
SVG (Scalable Vector Graphics) describes shapes in markup, such as <circle>, <rect>, and <path>. Each shape is a real element in the DOM, just like a <div>. You can select it, give it a class, style it with CSS, and attach event listeners to it. To change it, you change an attribute (setAttribute('r', 40)) and the browser redraws it for you. Because it's vector, it stays sharp at any size.
SVG projects often start in Illustrator. Put each part you want to make interactive on its own layer, and give it a simple name like door or left-eye. When you export with File > Export > Export As > SVG and set Object IDs to Layer Names, each layer becomes a <g id="..."> group in the code. Paste that SVG code directly into your HTML instead of linking it with <img>. Then JavaScript can select each layer by its id, like document.querySelector('#door'), and make it respond to clicks, hovers, or animation.
Canvas: drawing & painting
A <canvas> is a blank grid of pixels. You draw on it with JavaScript commands like fillRect(), arc(), and drawImage(). Once something is drawn, the canvas forgets it was a "shape." There is only paint. There are no elements to select or move, so to animate you clear the canvas and redraw everything, usually many times per second with requestAnimationFrame().
Use it when you have lots of things moving at once, or you want to work at the pixel level. Examples: particle systems, generative art, games, drawing and painting tools, visual effects and filters on images or video frames, simulations with hundreds or thousands of objects.
HTML5 Audio & Video
Sound and moving image are often the fastest way to give a project mood. They also combine easily with everything else this week: a click on an SVG shape plays a sound, a video drives a canvas, a game event triggers a sound effect.
There are two ways to get audio or video into your page. You can write the element in your HTML and grab it with JavaScript, or you can create it entirely in JavaScript. Once you have it, the controls are the same either way.
Audio with JavaScript
<!-- Option 1: element in the HTML -->
<audio id="chime" src="chime.mp3"></audio>
const chime = document.getElementById('chime');
// Option 2: create it in JavaScript (nothing needed in the HTML)
const chime = new Audio('chime.mp3');
// Either way, control it the same:
chime.play(); // play it
chime.pause(); // pause it
chime.currentTime = 0; // rewind to the start (so it can retrigger)
chime.volume = 0.5; // 0 to 1
chime.loop = true; // repeat
Audio made with new Audio() never appears on the page. That's fine for sound effects and background audio you trigger with code. If you want visible play/pause controls, put an <audio controls> element in the HTML instead.
Video with JavaScript
<!-- Option 1: element in the HTML -->
<video id="clip" src="clip.mp4" muted playsinline></video>
const clip = document.getElementById('clip');
// Option 2: create it in JavaScript
const clip = document.createElement('video');
clip.src = 'clip.mp4';
clip.muted = true;
clip.playsInline = true;
document.body.appendChild(clip); // add it to the page so it can be seen
// Either way, control it the same:
clip.play();
clip.pause();
clip.playbackRate = 0.5; // slow motion (2 = double speed)
clip.currentTime = 10; // jump to 10 seconds
// Run code as the video plays
clip.addEventListener('timeupdate', () => {
console.log(clip.currentTime + ' / ' + clip.duration);
});
// Run code when it finishes
clip.addEventListener('ended', () => {
console.log('done');
});
Unlike audio, a video has to be added to the page with appendChild() to be seen. Creating it in JavaScript is useful when the video depends on what the user does, like loading a different clip based on a choice.
Demos:
Tips and Resources:
- Browsers block sound until the user interacts (a click or key press). Start audio inside an event listener, not on page load.
- Use
.mp3for audio and.mp4(H.264) for video for the widest browser support. - Canvas can draw video frames:
ctx.drawImage(clip, 0, 0, 600, 400)inside an animation loop. That is one way to combine video and Canvas. - References: HTML Audio/Video DOM Reference
Canvas: JS Drawing
- A blank drawing surface that JavaScript paints onto using coordinates, like a digital sketchpad.
- Once something is drawn, it doesn’t remain as a separate object in the DOM. It becomes pixels.
- To change anything, you clear the canvas and redraw everything. This is why drawing code usually lives inside a function, like
drawFace(). - Better suited than SVG for particle systems, physics, generative art, constantly updating visuals, and games.
Setting Up
<canvas id="myCanvas" width="600" height="600"></canvas>
const c = document.getElementById('myCanvas');
const ctx = c.getContext('2d'); // the drawing toolkit
Important: CSS width and height only change the display size. The drawing size comes from the width and height attributes on the <canvas> tag. If CSS stretches a 600 × 600 canvas to 800px, your drawing commands still use 600 × 600 coordinates.
Basic Drawing Methods
beginPath()– Begins a new path or resets the current path.moveTo(x, y)– Moves the “pen” to a starting position without drawing.lineTo(x, y)– Draws a straight line from the current position to the given coordinates.arc(x, y, radius, startAngle, endAngle, counterclockwise)– Draws a circle or arc.rect(x, y, width, height)– Draws a rectangle.fill()– Fills the current shape withfillStyle.stroke()– Outlines the current path withstrokeStyleandlineWidth.closePath()– Connects the last point to the first, closing the shape.clearRect(0, 0, c.width, c.height)– Erases the canvas before redrawing.-
Adding text:
ctx.font = "30px Arial";
ctx.fillText("Hello, Canvas!", 50, 200);
ctx.fillText(text, x, y, [maxWidth])– maxWidth scales the text to fit. - Use
ctx.save()andctx.restore()to reset settings and avoid affecting later drawings.
Drawing Circles and Arcs
- ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise);
- x, y: The center of the arc
- radius: The distance from the center to the edge
- startAngle / endAngle: In radians.
0toMath.PIis a half circle (bottom half);0to2 * Math.PIis a full circle. - counterclockwise (optional):
truedraws counterclockwise (clockwise by default)
Mouse Position on the Canvas
c.addEventListener('mousemove', (e) => {
const rect = c.getBoundingClientRect(); // canvas position on the page
const mx = e.clientX - rect.left; // mouse x inside the canvas
const my = e.clientY - rect.top; // mouse y inside the canvas
drawFace(mx, my); // redraw with new values
});
Demos
- Canvas Smiley: Drawing — the face built step by step with paths and arcs
- Canvas Smiley: Interaction — pupils follow the mouse, kept inside the eye
- Canvas Element | Canvas Reference
SVG (Scalable Vector Graphics) and JS
- Best used when you want crisp, scalable graphics that stay sharp at any size and can be easily changed with JavaScript.
- SVG is made of vector shapes (lines, paths, circles, text). Each part of the graphic exists as an individual element in the HTML.
- Select pieces with JavaScript or CSS and change their color, size, or position, or trigger small animations like hover effects, fades, rotations, or simple movements.
- Ideal for logos, icons, diagrams, infographics, maps, and illustrations where interaction is light but precise.
- Create artwork in Adobe Illustrator, then export it as SVG (File → Export → Export As → SVG). Paste the
<svg>...</svg>code directly into your HTML so you can target individual shapes with JavaScript.
From Illustrator to JavaScript
- Name your layers clearly in Illustrator before exporting. Layer names become
ids. - Export as SVG and open the SVG code.
- Paste the
<svg>block into your HTML. - Check that the ids match what you expect, then select them with
getElementById().
Mouse Position on the Canvas
c.addEventListener('mousemove', function (e) {
const mx = e.offsetX; // mouse x inside the canvas
const my = e.offsetY; // mouse y inside the canvas
drawFace(mx, my); // redraw with new values
});
- Common attributes:
circle→cx, cy, r·rect→x, y, width, height, rx·line→x1, y1, x2, y2·ellipse→cx, cy, rx, ry· any shape →fill, stroke, stroke-width, opacity, transform - Path data (
d):M= move to,L= line to,A= arc,Z= close. For example,M 220,370 A 80,80 0 0,0 380,370draws a smile. Flip the last flag to1to make it a frown. - viewBox gives SVG its own coordinate space.
viewBox="0 0 600 600"means shapes use 600 × 600 units, whatever size the SVG is displayed at. To get mouse position in SVG units, scale it:(e.clientX - rect.left) * (600 / rect.width).
Demos
- SVG Smiley — every shape is a live element; pupils follow the mouse with
setAttribute() - svg-smiley-interactive.html
- Von Miller’s interactive website: Phone Game
- Shannon Guo'sColor Mixing Gae
- SVG Clock — design element
SVG + JavaScript Resources
- W3Schools: SVG Introduction: the basic shapes and attributes
- W3Schools: SVG Scripting: changing SVG attributes with JavaScript
- MDN: SVG Tutorial: the full reference, from shapes and paths to transforms
- Josh Comeau: A Friendly Introduction to SVG: clear visual explanations with interactive demos
- Chris Coyier: Practical SVG: a free online book covering embedding, styling, and animation
- Export SVGs for Web from Illustrator: short guide to the Export As workflow and layer-name IDs
- SitePoint: Optimizing and Exporting SVGs in Illustrator: more detail on the export settings and naming
- Algonquin Design: Exporting from Illustrator: course page on naming layers so they become IDs you can target with CSS and JS
Compare: open the SVG Smiley and the Canvas Smiley side by side. Both make the pupils follow the mouse with the same constrainPupil() math. SVG moves two circles with setAttribute(). Canvas clears and repaints the whole face on every mouse move.
Wednesday: Canvas Animation & p5.js
Canvas Animation
Canvas animation is drawing frame by frame. Each frame you clear the canvas, update values (position, size, color), and redraw. Repeat that many times per second and you get motion.
The Animation Loop
let x = 0; // position
let speed = 2; // velocity: how far it moves each frame
function animate() {
ctx.clearRect(0, 0, c.width, c.height); // 1. clear
x += speed; // 2. update
if (x > c.width || x < 0) speed *= -1; // bounce at the edges
ctx.beginPath(); // 3. draw
ctx.arc(x, 300, 20, 0, 2 * Math.PI);
ctx.fill();
requestAnimationFrame(animate); // 4. repeat
}
animate();
requestAnimationFrame()asks the browser to call your function before the next repaint, about 60 times per second. It is smoother than a timer and pauses when the tab is hidden.setTimeout()/setInterval()are fine for slow, stepped changes, like the face’s eyes shifting once per second.- Many objects: store them in an array and update each one with
forEach(). That is how the rain and snow demos work.
Demos
- Example Face 1
- Example Face 2 - drift
- canvas-animation.html
- canvas-rainfall-demo.html
- canvas-snowfall.html
Generative Art
Generative visual art is digital art made with algorithms. The artist sets the rules and the starting point; the computer follows those rules and produces the final piece, often a little different every time it runs.
GENERATIVE ART: Art created using autonomous processes
AUTONOMOUS PROCESS: A process not under direct human control
Vera Molnár
Vera Molnár (1924–2023) was a Hungarian-French artist and one of the earliest pioneers of computer-based art. In the late 1960s she began using computers to explore geometric forms through small, methodical variations. Her series show how a simple rule plus a little randomness can produce real aesthetic complexity.
p5.js
p5.js is the JavaScript version of Processing, a programming language created in 2001 by Casey Reas and Ben Fry at the MIT Media Lab. They designed Processing to teach coding to artists and designers, with a focus on visual results rather than software engineering. In 2013, artist Lauren Lee McCarthy started p5.js to bring that approach to the web. The names in p5.js, like setup(), draw(), and background(), come straight from Processing, so Processing tutorials and books mostly carry over.
p5.js is a JavaScript library that makes Canvas drawing and animation simpler. It runs the animation loop for you and adds tools for randomness and noise. Paste each example into the p5.js editor, press play, then change the numbers.
Using p5.js on Your Own Page
The p5.js editor loads the library for you. On your own webpage, you have to load it yourself. Add a link to the p5.js library at the bottom of your page, just before your own script, whether that's a <script> block or a link to your sketch file. The library has to come first, because your sketch uses functions like setup(), draw(), and circle() that p5.js provides. You don't need to create a <canvas> element; createCanvas() makes one for you.
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="sketch.js"></script>
</body>
1. setup() and draw()
function setup() { // runs once at the start
createCanvas(600, 400); // make a canvas 600 wide, 400 tall
}
function draw() { // runs over and over, about 60 times per second
background(20); // fill the canvas with a dark gray
fill(255, 120, 80); // set the color for the next shapes (orange)
circle(300, 200, 100); // draw a circle
rect(50, 50, 80, 80); // draw a rectangle
}
setup() runs once. draw() repeats every frame. It replaces the requestAnimationFrame() loop you wrote yourself in plain Canvas.
createCanvas(width, height): the size of the canvas in pixels.background(gray): one number from 0 (black) to 255 (white). You can also give three numbers for red, green, blue.fill(red, green, blue): each value runs from 0 to 255. Every shape drawn after this uses that color until you callfill()again.circle(x, y, diameter): x and y are the center of the circle. The third value is the diameter (the full width), not the radius.rect(x, y, width, height): x and y are the top-left corner.
Explore in the editor: change values and see results.
2. Animating with frameCount
function setup() {
createCanvas(600, 400);
}
function draw() {
background(20);
circle(frameCount, 200, 40); // x position = the frame number
}
frameCount is a built-in variable that counts how many times draw() has run: 1, 2, 3, 4… It works as a clock. Here it becomes the circle's x position, so the circle moves one pixel to the right every frame. Once it passes the edge of the canvas, it keeps going and disappears.
frameCount * 3moves faster.frameCount * 0.5moves slower.widthandheightare built-in variables that hold the canvas size (here, 600 and 400).circle(frameCount, height / 2, 40)keeps the circle in the vertical middle even if you change the canvas size.
Why redraw background() every frame? It wipes the previous frame. Comment it out and see what happens.
Explore in the editor: change values and see results.
3. Responding to the mouse with map()
function setup() {
createCanvas(600, 400);
}
function draw() {
let shade = map(mouseX, 0, width, 0, 255);
background(shade);
fill(255 - shade); // the opposite shade, so the circle stays visible
circle(mouseX, mouseY, 50);
}
mouseX and mouseY are built-in variables that hold the mouse position on the canvas.
This map() is not the array .map() you already know. It is a p5.js math function with the same name. It converts a number from one range to another:
map(value, fromLow, fromHigh, toLow, toHigh)
The mouse can be anywhere from 0 to 600 (width), but a color only goes from 0 to 255. map() translates between the two scales:
- Mouse at 0 → shade 0 (black)
- Mouse at 300 (halfway) → shade about 127 (gray)
- Mouse at 600 → shade 255 (white)
Explore in the editor: change values and see results.
4. random(): scatter
function setup() {
createCanvas(600, 400);
background(20); // background only once, so circles pile up
}
function draw() {
noStroke(); // no outline on shapes
fill(255, 80); // white, mostly transparent
let x = random(width); // any number from 0 to 600
let y = random(height); // any number from 0 to 400
let size = random(5, 40); // any number from 5 to 40
circle(x, y, size);
}
random(max): a number from 0 up to max.random(min, max): a number between min and max.fill(gray, alpha): with two numbers, the second is transparency, from 0 (invisible) to 255 (solid). This is different from CSSrgba(), where alpha runs from 0 to 1.
Every frame gets brand-new values that have nothing to do with the last ones. The circles jump all over.
Explore in the editor: change values and see results.
5. noise(): drift
function setup() {
createCanvas(600, 400);
background(20);
}
function draw() {
let t = frameCount * 0.01; // a slowly increasing "time" value
noStroke();
fill(255, 80);
let x = noise(t) * width; // noise gives 0–1, times 600 = 0–600
let y = noise(t + 100) * height; // a different spot in the noise, so y doesn't match x
let size = noise(t + 200) * 40; // 0–40
circle(x, y, size);
}
noise(t) always returns a number between 0 and 1. Unlike random(), the same t always gives the same answer, and nearby t values give nearby answers. If t moves forward in small steps, the output changes smoothly. Multiplying by width stretches the 0–1 result across the canvas.
frameCount * 0.01is the step size.0.001is slower and smoother;0.1is faster and more jittery.t + 100andt + 200read from different places in the noise, so x, y, and size each wander on their own.
Examples 4 and 5 draw the same thing. The only difference is random() vs. noise(). Run them side by side. What mood does each one have?
Note: p5.js arc(x, y, w, h, start, stop) uses width and height; Canvas arc(x, y, radius, start, end) uses a radius.
Explore in the editor: change values and see results.
Two Kinds of Chance: random() vs. noise()
random() gives a new, unrelated value each time. Things jump, flicker, and scatter.
noise() (Perlin noise) gives values that change gradually. Things drift, flow, and breathe, like clouds, water, or terrain.
Images from Amy Goodchild’s What is Generative Art. Try it yourself: random() vs noise().
Terms to Play with in AI
Ask AI for a p5.js sketch using one or two of these terms. Then change the rules and values yourself. A simple pattern: “Write a p5.js sketch that uses [term] and noise() to create [mood].”
- Flow field — particles steered by an invisible grid of directions (Tyler Hobbs on flow fields)
- Particle system — many small things born, moving, and fading
- Trails — a semi-transparent
background()so motion leaves a ghost - Perlin noise terrain / clouds — noise sampled across a grid
- Boids / flocking — separation, alignment, cohesion
- Fractal tree / recursion — a shape that draws smaller copies of itself
- Cellular automata — cells changing based on neighbors (Conway’s Game of Life)
- Interrupted grid — a Molnár-style grid with small random disruptions
- Polar coordinates / spiral — positions from angle and distance
- Sine wave / oscillation —
sin(frameCount * 0.05)for pulsing and swinging - Lissajous curve — two sine waves combined into looping figures
- Blend modes —
blendMode(ADD)for glowing overlaps
Going Deeper
My Sketches and Demos
- Shapes
- Square grid
- Bouncing balls
- JavaScript Canvas with p5.js
- p5.js — Perlin Noise
- p5.js — Flow Fields
- p5.js HTML starter template — for moving a sketch from the editor to your own page
Learning and Inspiration
- p5.js reference and examples
- The Coding Train p5.js tutorials
- The Nature of Code — free book on simulating motion, forces, and natural systems
- How to code generative art with p5.js
- Amy Goodchild, What is Generative Art
- OpenProcessing — community of generative artists
- p5.js showcase