Mouse Interaction
Read mouse position and clicks to make your sketches respond to the viewer.
Built-in mouse variables
p5.js automatically tracks the mouse and stores its state in several global variables:
| Variable | Description |
|---|---|
mouseX |
Current mouse x position on the canvas |
mouseY |
Current mouse y position on the canvas |
pmouseX |
Mouse x position in the previous frame |
pmouseY |
Mouse y position in the previous frame |
mouseIsPressed |
true while any mouse button is held down |
mouseButton |
LEFT, RIGHT, or CENTER |
These update automatically every frame — just read them.
A simple paint brush
function setup() {
createCanvas(600, 400);
background(20);
}
function draw() {
if (mouseIsPressed) {
stroke(255, 150, 50);
strokeWeight(4);
// Draw a line from previous position to current — avoids gaps when moving fast
line(pmouseX, pmouseY, mouseX, mouseY);
}
}
The pmouseX / pmouseY trick is important. If you just draw a circle at mouseX, mouseY the user can move the mouse faster than the frame rate and leave gaps. Connecting previous and current positions with a line fills them in.
mousePressed() and mouseReleased()
For one-off actions (not held-down), use event functions:
function mousePressed() {
// Runs once each time a mouse button is pressed
}
function mouseReleased() {
// Runs once each time a mouse button is released
}
function mouseClicked() {
// Runs once after a press + release (full click)
}
function doubleClicked() {
// Runs on double-click
}
Example — add a circle on each click:
let circles = [];
function setup() {
createCanvas(600, 400);
background(20);
}
function draw() {
background(20);
noStroke();
for (let c of circles) {
fill(c.r, c.g, c.b, 200);
circle(c.x, c.y, c.size);
}
}
function mouseClicked() {
circles.push({
x: mouseX,
y: mouseY,
size: random(20, 80),
r: random(100, 255),
g: random(50, 200),
b: random(100, 255)
});
}
mouseScrolled / mouseWheel
function mouseWheel(event) {
// event.delta is positive scrolling down, negative scrolling up
let delta = event.delta;
// Use delta to zoom, change size, etc.
}
Detecting hover over a region
p5.js doesn’t have built-in button components, but you can check bounds manually:
function isMouseOver(x, y, w, h) {
return mouseX > x && mouseX < x + w &&
mouseY > y && mouseY < y + h;
}
function draw() {
background(20);
let hovering = isMouseOver(200, 150, 200, 100);
fill(hovering ? color(100, 200, 100) : color(60, 60, 80));
rect(200, 150, 200, 100, 8);
fill(255);
textAlign(CENTER, CENTER);
textSize(16);
text('Click me', 300, 200);
}
function mouseClicked() {
if (isMouseOver(200, 150, 200, 100)) {
background(random(255), random(255), random(255));
}
}
Distance-based interaction
dist(x1, y1, x2, y2) gives the distance between two points. Great for circular hover detection:
let bx = 300, by = 200;
function draw() {
background(20);
let d = dist(mouseX, mouseY, bx, by);
let isNear = d < 80;
fill(isNear ? color(255, 200, 50) : color(80, 80, 120));
noStroke();
circle(bx, by, 80);
}
Cursor styles
cursor(HAND); // pointer hand
cursor(CROSS); // crosshair
cursor(ARROW); // default arrow
cursor(MOVE); // move arrows
cursor(TEXT); // text cursor
noCursor(); // hide the cursor entirely
Touch devices
On touch screens, mouseX and mouseY map to the first touch point, and mouseIsPressed is true while a finger is on the screen. For more complex multi-touch, use the touches array:
function draw() {
background(20);
noStroke();
fill(255, 100, 50, 150);
for (let t of touches) {
circle(t.x, t.y, 60);
}
}
Key takeaways
mouseX,mouseY— current cursor position (updated every frame)pmouseX,pmouseY— position in the previous frame (useful for drawing smooth lines)mouseIsPressed— true while a button is heldmousePressed(),mouseReleased(),mouseClicked()— event callbacks for one-off actionsdist()is the cleanest way to check circular hover areascursor()changes the cursor appearance- Touch screens map the first touch to the mouse variables; use
touches[]for multi-touch