// p5 Hero — Instance Mode
const hero = function(p) {
let balls = [];
const colors = [
[200, 30, 70], [50, 100, 220], [250, 180, 30],
[30, 180, 120], [160, 60, 210], [240, 90, 40]
];
p.setup = function() {
let canvas = p.createCanvas(p.windowWidth, 400);
canvas.position(0, 0);
for (let i = 0; i < 35; i++) {
balls.push({
x: p.random(p.width), y: p.random(p.height),
homeX: 0, homeY: 0,
size: p.random(20, 56),
speed: p.random(0.2, 0.8),
col: colors[i % colors.length]
});
balls[i].homeX = balls[i].x;
balls[i].homeY = balls[i].y;
}
};
p.draw = function() {
p.background(30, 30, 60);
p.noStroke();
for (let b of balls) {
b.homeY += b.speed;
if (b.homeY > p.height + 40) {
b.homeY = -40;
b.homeX = p.random(p.width);
b.x = b.homeX;
}
let d = p.dist(p.mouseX, p.mouseY, b.x, b.y);
if (d < 120) {
let angle = p.atan2(b.y - p.mouseY, b.x - p.mouseX);
let push = p.map(d, 0, 120, 3, 0);
b.x += p.cos(angle) * push;
b.y += p.sin(angle) * push;
}
b.x = p.lerp(b.x, b.homeX, 0.03);
b.y = p.lerp(b.y, b.homeY, 0.03);
p.fill(b.col[0], b.col[1], b.col[2]);
p.circle(b.x, b.y, b.size);
p.fill(b.col[0]*0.6, b.col[1]*0.6, b.col[2]*0.6);
let s = b.size / 44;
p.circle(b.x - 4*s, b.y - 5*s, 6*s);
p.circle(b.x + 4*s, b.y - 5*s, 6*s);
p.circle(b.x, b.y + 3*s, 6*s);
}
};
p.windowResized = function() {
p.resizeCanvas(p.windowWidth, 400);
};
};
new p5(hero, document.getElementById('hero-sketch'));
// HTML
<div class="hero" id="hero-sketch">
<div class="hero-overlay">
<h1>...</h1>
</div>
</div>
// CSS
.hero { position: relative; overflow: hidden; }
.hero canvas { position: absolute; top: 0; left: 0; }
.hero-overlay { position: relative; z-index: 1; }