The Tyranny of the Perfect Moment
About This Sketch
Float around randomly
This sketch accompanies the blog post "The Tyranny of the Perfect Moment" and visualizes its core concepts through generative art.
Algorithm
Float around randomly
This sketch was originally created as a visual companion to the blog post "The Tyranny of the Perfect Moment" and explores its themes through generative art.
Pseudocode
SETUP:
Initialize canvas (400x300)
Set up drawing parameters
DRAW (every frame):
Get current theme colors
Clear background
Draw generative visualization
Update animation state
Source Code
let sketch = function(p) {
let ideas = [];
let capturedIdeas = [];
let time = 0;
class Idea {
constructor() {
this.x = p.random(50, 350);
this.y = p.random(50, 150);
this.vx = p.random(-1, 1);
this.vy = p.random(-1, 1);
this.brightness = 255; // starts bright
this.fadeRate = 1; // fades over time if not captured
this.size = p.random(8, 15);
this.captured = false;
this.captureY = null;
this.wobble = p.random(p.TWO_PI);
}
update() {
if (!this.captured) {
// Float around randomly
this.x += this.vx;
this.y += this.vy;
// Bounce off edges
if (this.x < 20 || this.x > 380) this.vx *= -1;
if (this.y < 20 || this.y > 180) this.vy *= -1;
// Fade over time (inspiration fading)
this.brightness -= this.fadeRate;
// Check if near capture zone (mobile device area)
if (this.y > 200 && this.brightness > 50) {
this.captured = true;
this.captureY = this.y;
capturedIdeas.push(this);
}
} else {
// Once captured, settle into organized position
this.y = p.lerp(this.y, 250, 0.05);
this.brightness = 255; // stays bright when captured
}
}
display(colors) {
if (this.brightness <= 0) return; // completely faded
let alpha = p.map(this.brightness, 0, 255, 0, 200);
if (this.captured) {
// Captured ideas are solid and stable
p.fill(...colors.accent2, alpha);
p.noStroke();
} else {
// Uncaptured ideas are fading
let wobbleX = p.sin(time * 2 + this.wobble) * 2;
let wobbleY = p.cos(time * 2 + this.wobble) * 2;
p.fill(...colors.accent1, alpha);
p.noStroke();
p.ellipse(this.x + wobbleX, this.y + wobbleY, this.size, this.size);
return;
}
p.ellipse(this.x, this.y, this.size, this.size);
}
isDead() {
return !this.captured && this.brightness <= 0;
}
}
p.setup = function() {
p.createCanvas(400, 300);
p.colorMode(p.RGB);
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
// Draw the "ideal workspace" zone (top)
p.fill(...colors.accent3, 30);
p.noStroke();
p.rect(0, 0, 400, 180);
p.fill(...colors.accent3, 150);
p.textAlign(p.CENTER, p.TOP);
p.textSize(10);
p.text("'I'll capture this when I get to my desk...'", 200, 10);
// Draw the capture zone (mobile device at bottom)
p.fill(...colors.accent2, 50);
p.rect(0, 200, 400, 2);
p.fill(...colors.accent3, 150);
p.textAlign(p.CENTER, p.BOTTOM);
p.textSize(10);
p.text("Capture zone: Create now, wherever you are", 200, 290);
// Draw captured ideas count
p.textAlign(p.LEFT, p.TOP);
p.textSize(9);
p.fill(...colors.accent2, 200);
p.text("Captured: " + capturedIdeas.length, 10, 265);
// Spawn new ideas occasionally
if (p.frameCount % 90 === 0 && ideas.length < 12) {
ideas.push(new Idea());
}
// Update and display ideas
for (let i = ideas.length - 1; i >= 0; i--) {
ideas[i].update();
ideas[i].display(colors);
// Remove dead (faded) ideas
if (ideas[i].isDead()) {
ideas.splice(i, 1);
}
}
// Visual indicator: ideas fade (get dimmer) as they wait
p.textAlign(p.RIGHT, p.TOP);
p.textSize(8);
p.fill(...colors.accent3, 130);
p.text("Ideas fade while you wait", 390, 170);
time += 0.02;
};
};