setup()
setup() runs once when the sketch starts. It is the perfect place to create your canvas, initialize variables, and build any interactive DOM elements (buttons, inputs, text fields) that p5.js provides. Notice how createDiv(), createButton(), and createInput() let you build an entire HTML interface directly in JavaScript without touching index.html.
🔬 These three lines use z-index to layer the canvas behind the UI. What happens if you change '-1' to '1' so the canvas appears on top of the buttons instead?
canvasContainer.style('z-index', '-1'); // Send canvas to background
let canvas = createCanvas(windowWidth, windowHeight);
canvas.parent(canvasContainer);
function setup() {
// Create canvas and parent it to a div. This div will be placed behind the UI.
// Using position: absolute and z-index: -1 ensures the canvas fills the background
// and doesn't interfere with the UI elements.
let canvasContainer = createDiv();
canvasContainer.style('position', 'absolute');
canvasContainer.style('top', '0');
canvasContainer.style('left', '0');
canvasContainer.style('z-index', '-1'); // Send canvas to background
let canvas = createCanvas(windowWidth, windowHeight);
canvas.parent(canvasContainer);
// --- UI Elements ---
// Create a container div for all UI elements.
// We'll style this div using absolute positioning to center it on the screen.
let uiContainer = createDiv();
uiContainer.style('padding', '20px');
uiContainer.style('background-color', 'rgba(255, 255, 255, 0.8)'); // Semi-transparent background
uiContainer.style('border-radius', '10px');
uiContainer.style('position', 'absolute');
uiContainer.style('top', '50%');
uiContainer.style('left', '50%');
uiContainer.style('transform', 'translate(-50%, -50%)'); // Center the div
uiContainer.style('text-align', 'center');
uiContainer.style('box-shadow', '0 4px 8px rgba(0,0,0,0.2)'); // Add a subtle shadow
// Label for the duration input
let durationLabel = createElement('label', 'Set Timer (seconds): ');
durationLabel.style('display', 'block'); // Make it take full width
durationLabel.style('margin-bottom', '10px');
durationLabel.parent(uiContainer);
// Input field for setting the timer duration
durationInput = createInput(timerDuration.toString(), 'number');
durationInput.attribute('min', '1'); // Minimum value is 1 second
durationInput.attribute('step', '1'); // Allow only whole numbers
durationInput.style('width', '100px');
durationInput.style('padding', '8px');
durationInput.style('margin-bottom', '15px');
durationInput.style('border', '1px solid #ccc');
durationInput.style('border-radius', '4px');
durationInput.parent(uiContainer);
// Start Button
startButton = createButton('Start Timer');
startButton.style('padding', '10px 20px');
startButton.style('margin', '5px');
startButton.style('background-color', '#4CAF50'); // Green color
startButton.style('color', 'white');
startButton.style('border', 'none');
startButton.style('border-radius', '5px');
startButton.style('cursor', 'pointer');
startButton.style('font-size', '1em');
startButton.parent(uiContainer);
startButton.mousePressed(startTimer); // Attach the startTimer function to click event
// Reset Button
resetButton = createButton('Reset Timer');
resetButton.style('padding', '10px 20px');
resetButton.style('margin', '5px');
resetButton.style('background-color', '#f44336'); // Red color
resetButton.style('color', 'white');
resetButton.style('border', 'none');
resetButton.style('border-radius', '5px');
resetButton.style('cursor', 'pointer');
resetButton.style('font-size', '1em');
resetButton.parent(uiContainer);
resetButton.mousePressed(resetTimer); // Attach the resetTimer function to click event
// Timer Display
timerDisplay = createDiv(formatTime(timerDuration)); // Initialize with default duration
timerDisplay.style('font-size', '3em');
timerDisplay.style('font-weight', 'bold');
timerDisplay.style('margin-top', '20px');
timerDisplay.style('color', '#333');
timerDisplay.parent(uiContainer);
// --- Initialize Bouncing Shape ---
// Start the bouncing shape at the center of the canvas
bounceX = width / 2;
bounceY = height / 2;
// Give it a random initial velocity
bounceVX = random(3, 7) * (random() > 0.5 ? 1 : -1); // Random speed between 3 and 7, random direction
bounceVY = random(3, 7) * (random() > 0.5 ? 1 : -1);
}
Line-by-line explanation (19 lines)
🔧 Subcomponents:
canvasContainer.style('z-index', '-1');
Places the canvas behind the UI by assigning it a negative z-index, so buttons and text appear on top
uiContainer.style('transform', 'translate(-50%, -50%)');
Mathematically centers the panel horizontally and vertically by offsetting its position by half its own width and height
startButton.mousePressed(startTimer);
Attaches the startTimer function so it runs when the user clicks the Start button
bounceVX = random(3, 7) * (random() > 0.5 ? 1 : -1);
Generates a random speed between 3 and 7, then randomly chooses a direction (positive or negative) so the circle bounces in an unpredictable direction
let canvasContainer = createDiv();- Creates an empty HTML div that will hold the p5.js canvas, allowing us to position it independently of the UI
canvasContainer.style('z-index', '-1');- Sets the z-index (layering depth) to -1, so the canvas appears behind everything else on the page
let canvas = createCanvas(windowWidth, windowHeight);- Creates a p5.js canvas that fills the entire browser window using windowWidth and windowHeight
canvas.parent(canvasContainer);- Attaches the canvas to the canvasContainer div, making it a child element so the z-index layering works correctly
let uiContainer = createDiv();- Creates a new div to hold all the UI controls (input, buttons, timer display) in one organized container
uiContainer.style('position', 'absolute');- Makes the UI container position itself relative to the window rather than the normal document flow, allowing free placement
uiContainer.style('top', '50%');- Positions the top of the container 50% down the page (not quite centered because we haven't offset for its height yet)
uiContainer.style('left', '50%');- Positions the left edge of the container 50% across the page width
uiContainer.style('transform', 'translate(-50%, -50%)');- Shifts the container left by 50% of its own width and up by 50% of its own height, centering it perfectly on screen
let durationLabel = createElement('label', 'Set Timer (seconds): ');- Creates an HTML label element with the text 'Set Timer (seconds): ' to describe the input field below it
durationInput = createInput(timerDuration.toString(), 'number');- Creates a text input field of type 'number' and pre-fills it with the current timerDuration value converted to a string
durationInput.attribute('min', '1');- Sets a minimum value of 1 second—the browser won't allow the user to enter lower values
durationInput.attribute('step', '1');- Restricts input to whole numbers only, preventing decimal values like 30.5 seconds
startButton.mousePressed(startTimer);- Registers the startTimer function to run whenever the user clicks the Start Timer button
resetButton.mousePressed(resetTimer);- Registers the resetTimer function to run whenever the user clicks the Reset Timer button
timerDisplay = createDiv(formatTime(timerDuration));- Creates a large text display and initializes it by calling formatTime() to show the timer duration in MM:SS format
bounceX = width / 2;- Places the bouncing circle's starting x-position at the horizontal center of the canvas
bounceY = height / 2;- Places the bouncing circle's starting y-position at the vertical center of the canvas
bounceVX = random(3, 7) * (random() > 0.5 ? 1 : -1);- Generates a random horizontal velocity between 3 and 7 pixels per frame, then randomly flips its sign so the circle moves left or right with equal probability