setup()
setup() runs once when the sketch starts. Here it prepares the canvas, sets the color system, and wires up dozens of dat.GUI sliders to the params object so every other function can read live, user-adjustable values instead of hardcoded numbers.
🔬 These sliders' maximum range is tied to min(width, height) / 2, so it automatically scales with canvas size. What happens if you replace that with a fixed number like 300 - will the sliders still make sense if you resize the browser window afterward?
const outerFolder = gui.addFolder('Outer Polygons');
outerFolder.add(params, 'outerDistanceMin', 50, min(width, height) / 2).name('Dist Min');
outerFolder.add(params, 'outerDistanceMax', 50, min(width, height) / 2).name('Dist Max');
function setup() {
createCanvas(windowWidth, windowHeight);
colorMode(HSB, 360, 100, 100, 100);
noStroke();
// Setup dat.gui
gui = new dat.GUI();
// General controls
gui.add(params, 'hueSpeed', 0.1, 2.0).name('Hue Shift Speed');
gui.add(params, 'overallAlpha', 20, 100).name('Overall Alpha');
gui.add(params, 'saturationMin', 0, 100).name('Sat Min');
gui.add(params, 'saturationMax', 0, 100).name('Sat Max');
gui.add(params, 'brightnessMin', 0, 100).name('Bright Min');
gui.add(params, 'brightnessMax', 0, 100).name('Bright Max');
// Outer Polygons
const outerFolder = gui.addFolder('Outer Polygons');
outerFolder.add(params, 'outerDistanceMin', 50, min(width, height) / 2).name('Dist Min');
outerFolder.add(params, 'outerDistanceMax', 50, min(width, height) / 2).name('Dist Max');
outerFolder.add(params, 'outerSizeMin', 5, 100).name('Size Min');
outerFolder.add(params, 'outerSizeMax', 5, 100).name('Size Max');
outerFolder.add(params, 'outerSidesMin', 3, 10, 1).name('Sides Min');
outerFolder.add(params, 'outerSidesMax', 3, 10, 1).name('Sides Max');
outerFolder.add(params, 'outerRotationSpeed', -0.1, 0.1).name('Rotation Speed');
// Inner Stars
const innerFolder = gui.addFolder('Inner Stars');
innerFolder.add(params, 'innerDistanceMin', 10, min(width, height) / 3).name('Dist Min');
innerFolder.add(params, 'innerDistanceMax', 10, min(width, height) / 3).name('Dist Max');
innerFolder.add(params, 'innerStarPointsMin', 3, 10, 1).name('Points Min');
innerFolder.add(params, 'innerStarPointsMax', 3, 10, 1).name('Points Max');
innerFolder.add(params, 'innerRadius1Min', 5, 50).name('Inner Rad Min');
innerFolder.add(params, 'innerRadius1Max', 5, 50).name('Inner Rad Max');
innerFolder.add(params, 'innerRotationSpeed', -0.1, 0.1).name('Rotation Speed');
// Pulsing Circles
const pulseFolder = gui.addFolder('Pulsing Circles');
pulseFolder.add(params, 'pulseCount', 1, 10, 1).name('Count');
pulseFolder.add(params, 'pathRadiusMin', 10, min(width, height) / 3).name('Path Rad Min');
pulseFolder.add(params, 'pathRadiusMax', 10, min(width, height) / 3).name('Path Rad Max');
pulseFolder.add(params, 'pulseSizeMin', 2, 50).name('Size Min');
pulseFolder.add(params, 'pulseSizeMax', 2, 50).name('Size Max');
pulseFolder.add(params, 'pulseOffsetSpeed', -0.1, 0.1).name('Offset Speed');
// Animated Strip
const stripFolder = gui.addFolder('Animated Strip');
stripFolder.add(params, 'stripDistanceMin', 10, min(width, height) / 4).name('Dist Min');
stripFolder.add(params, 'stripDistanceMax', 10, min(width, height) / 4).name('Dist Max');
stripFolder.add(params, 'stripLengthMin', 10, 200).name('Length Min');
stripFolder.add(params, 'stripLengthMax', 10, 200).name('Length Max');
stripFolder.add(params, 'stripHeight', 5, 50).name('Height');
stripFolder.add(params, 'stripOffsetMin', -50, 50).name('Offset Min');
stripFolder.add(params, 'stripOffsetMax', -50, 50).name('Offset Max');
stripFolder.add(params, 'stripRotationSpeed', -0.1, 0.1).name('Rotation Speed');
// Small Shapes
const smallFolder = gui.addFolder('Small Shapes');
smallFolder.add(params, 'smallDistanceMin', 10, min(width, height) / 6).name('Dist Min');
smallFolder.add(params, 'smallDistanceMax', 10, min(width, height) / 6).name('Dist Max');
smallFolder.add(params, 'smallSizeMin', 2, 30).name('Size Min');
smallFolder.add(params, 'smallSizeMax', 2, 30).name('Size Max');
smallFolder.add(params, 'smallRotationSpeed', -0.1, 0.1).name('Rotation Speed');
// Spirograph
const spiroFolder = gui.addFolder('Spirograph');
spiroFolder.add(params, 'spiroR_min', 10, 200).name('R Min');
spiroFolder.add(params, 'spiroR_max', 10, 200).name('R Max');
spiroFolder.add(params, 'spiro_r_min', 5, 100).name('r Min');
spiroFolder.add(params, 'spiro_r_max', 5, 100).name('r Max');
spiroFolder.add(params, 'spiro_d_min', 0, 100).name('d Min');
spiroFolder.add(params, 'spiro_d_max', 0, 100).name('d Max');
spiroFolder.add(params, 'spiroRotationSpeed', -0.1, 0.1).name('Rotation Speed');
spiroFolder.add(params, 'spiroStrokeWeight', 0.5, 5).name('Stroke Weight');
spiroFolder.add(params, 'spiroFillAlpha', 0, 100).name('Fill Alpha');
spiroFolder.add(params, 'spiroStrokeAlpha', 0, 100).name('Stroke Alpha');
// Lissajous Curve
const lissajousFolder = gui.addFolder('Lissajous');
lissajousFolder.add(params, 'lissajous_A', 10, 200).name('Amplitude A');
lissajousFolder.add(params, 'lissajous_B', 10, 200).name('Amplitude B');
lissajousFolder.add(params, 'lissajous_a_min', 1, 10, 1).name('Freq a Min');
lissajousFolder.add(params, 'lissajous_a_max', 1, 10, 1).name('Freq a Max');
lissajousFolder.add(params, 'lissajous_b_min', 1, 10, 1).name('Freq b Min');
lissajousFolder.add(params, 'lissajous_b_max', 1, 10, 1).name('Freq b Max');
lissajousFolder.add(params, 'lissajous_delta_speed', -0.05, 0.05).name('Delta Speed');
lissajousFolder.add(params, 'lissajous_rotation_speed', -0.1, 0.1).name('Rotation Speed');
lissajousFolder.add(params, 'lissajous_stroke_weight', 0.5, 5).name('Stroke Weight');
lissajousFolder.add(params, 'lissajous_stroke_alpha', 0, 100).name('Stroke Alpha');
lissajousFolder.add(params, 'lissajous_fill_alpha', 0, 100).name('Fill Alpha');
// Recursive Polygons
const recursiveFolder = gui.addFolder('Recursive Polygons');
recursiveFolder.add(params, 'recursivePolygonMaxDepth', 1, 5, 1).name('Max Depth');
recursiveFolder.add(params, 'recursivePolygonShrinkFactor', 0.5, 0.99).name('Shrink Factor');
recursiveFolder.add(params, 'recursivePolygonRotationOffset', -0.1, 0.1).name('Rotation Offset');
recursiveFolder.add(params, 'recursivePolygonSize', 20, 200).name('Base Size');
recursiveFolder.add(params, 'recursivePolygonSides', 3, 10, 1).name('Sides');
recursiveFolder.add(params, 'recursivePolygonX', -min(width, height) / 3, min(width, height) / 3).name('X Position');
recursiveFolder.add(params, 'recursivePolygonY', -min(width, height) / 3, min(width, height) / 3).name('Y Position');
recursiveFolder.add(params, 'recursivePolygonHueOffset', 0, 360).name('Hue Offset');
// Dynamic Grid
const gridFolder = gui.addFolder('Dynamic Grid');
gridFolder.add(params, 'dynamicGridSize', 50, 400).name('Size');
gridFolder.add(params, 'dynamicGridDensity', 5, 20, 1).name('Density');
gridFolder.add(params, 'dynamicGridRotationSpeed', -0.1, 0.1).name('Rotation Speed');
gridFolder.add(params, 'dynamicGridExpansionSpeed', -0.05, 0.05).name('Expansion Speed');
gridFolder.add(params, 'dynamicGridStrokeWeight', 0.5, 3).name('Stroke Weight');
gridFolder.add(params, 'dynamicGridX', -min(width, height) / 3, min(width, height) / 3).name('X Position');
gridFolder.add(params, 'dynamicGridY', -min(width, height) / 3, min(width, height) / 3).name('Y Position');
}
Line-by-line explanation (7 lines)
createCanvas(windowWidth, windowHeight);- Creates a canvas that fills the entire browser window.
colorMode(HSB, 360, 100, 100, 100);- Switches from the default RGB color model to HSB (hue, saturation, brightness, alpha), with hue running 0-360 like a color wheel - this makes rainbow color cycling as simple as adding a number and wrapping with modulo.
noStroke();- Turns off outlines by default so shapes drawn later start with no stroke unless one is explicitly set.
gui = new dat.GUI();- Creates the floating control panel in the corner of the screen that all the sliders below will be added to.
gui.add(params, 'hueSpeed', 0.1, 2.0).name('Hue Shift Speed');- Adds a slider bound directly to params.hueSpeed with a range of 0.1 to 2.0 - dragging it live-updates the variable the draw loop reads every frame.
const outerFolder = gui.addFolder('Outer Polygons');- Groups a set of related sliders into a collapsible folder so the panel stays organized instead of one huge list.
outerFolder.add(params, 'outerDistanceMin', 50, min(width, height) / 2).name('Dist Min');- One example of many folder sliders - this one's maximum range is calculated from the canvas size so it always makes sense regardless of screen dimensions.