Spinning Rainbow Color Wheel - xelsed.ai

This sketch draws a six-wedge rainbow pie chart that rotates continuously in the center of a black canvas. Each wedge is drawn with p5.js's arc() function in PIE mode, and a slowly incrementing rotation angle applied every frame creates the spinning hypnotic effect.

🧪 Try This!

Experiment with the code by making these changes:

  1. Speed up the spin — Increasing the amount added to rotationAngle each frame makes the wheel spin noticeably faster.
  2. Reverse the direction — Subtracting instead of adding to rotationAngle makes the wheel spin counter-clockwise instead of clockwise.
  3. Make the wheel fill the screen — Raising the wheelDiameter multiplier closer to 1 makes the wheel take up nearly the entire canvas.
  4. Add outlines between wedges — Removing noStroke() and adding a stroke color puts a visible line between each colored wedge.
Prefer the full editor? Open it there →

📖 About This Sketch

This sketch creates a spinning six-color pie wheel - red, orange, yellow, green, blue, and purple - that rotates endlessly on a black background. The mesmerizing effect comes from combining just three p5.js techniques: the arc() function drawn in PIE mode to create each wedge, translate() and rotate() to spin the whole wheel around its center, and a simple global angle variable that increases a tiny amount every frame.

The code is short and organized into just three functions: setup() prepares the canvas once, draw() runs 60 times a second to redraw the wheel at a new rotation angle, and windowResized() keeps the canvas full-screen. By studying it you'll learn how translate() moves the drawing origin, how arc()'s start/end angles slice a circle into equal parts using a for loop, and how continuously incrementing one variable produces smooth, endless animation.

⚙️ How It Works

  1. When the page loads, setup() creates a canvas that fills the browser window, sets angle mode to radians, and turns off shape outlines with noStroke()
  2. Every frame, draw() clears the screen to black and then moves the drawing origin to the exact center of the canvas using translate()
  3. The rotate() function tilts everything drawn afterward by the current value of rotationAngle, which is what makes the wheel appear to spin
  4. A for loop runs six times, once per color, calling arc() in PIE mode to draw each colored wedge as a slice of the same circle
  5. At the very end of draw(), rotationAngle is increased by a tiny amount (0.01 radians), so the next frame's rotate() call spins the wheel a little further
  6. Because draw() runs continuously, this tiny per-frame rotation accumulates into smooth, continuous spinning motion

🎓 Concepts You'll Learn

Animation loop with draw()translate() and rotate() transformsarc() in PIE modeFor loops for repeated drawingArrays of p5.Color objectsContinuous state increment for animation

📝 Code Breakdown

setup()

setup() runs exactly once when the sketch starts, making it the right place to configure the canvas and any drawing settings that shouldn't change every frame, like noStroke() or angleMode().

function setup() {
  createCanvas(windowWidth, windowHeight);
  angleMode(RADIANS); // default, but set explicitly for clarity
  noStroke();
}
Line-by-line explanation (3 lines)
createCanvas(windowWidth, windowHeight);
Creates a canvas that fills the entire browser window, using the browser's current width and height.
angleMode(RADIANS); // default, but set explicitly for clarity
Tells p5.js that angle values (like the rotation angle) are measured in radians rather than degrees. This is actually the default, but it's set explicitly here so the code's intent is clear to readers.
noStroke();
Turns off outlines on shapes, so each colored wedge blends smoothly into its neighbor without a border line.

draw()

draw() is p5.js's animation loop, running automatically about 60 times per second. Because translate() and rotate() affect everything drawn afterward within the same frame, and the canvas is fully redrawn each time via background(0), changing rotationAngle a tiny bit every frame is enough to produce smooth continuous rotation.

🔬 This loop divides the circle evenly based on wedgeCount, which comes from the length of the colors array. What happens visually if you add a 7th color to the colors array, or remove one to leave just 3? Will the wedge angles stay accurate?

  for (let i = 0; i < wedgeCount; i++) {
    fill(colors[i]);
    // Draw each wedge as a pie slice from center
    arc(
      0, 0,                  // centered at origin (already translated)
      wheelDiameter, wheelDiameter,
      i * step, (i + 1) * step,
      PIE                    // use PIE mode for wedge
    );
  }
function draw() {
  background(0); // black background

  // Center of canvas
  translate(width / 2, height / 2);

  // Slow continuous rotation
  rotate(rotationAngle);

  // Wheel size: 60% of the smaller canvas dimension
  const wheelDiameter = min(width, height) * 0.6;

  // 6 wedges: red, orange, yellow, green, blue, purple
  const colors = [
    color(255, 0, 0),      // red
    color(255, 127, 0),    // orange
    color(255, 255, 0),    // yellow
    color(0, 255, 0),      // green
    color(0, 0, 255),      // blue
    color(153, 0, 255)     // purple
  ];

  const wedgeCount = colors.length;
  const step = TWO_PI / wedgeCount;

  for (let i = 0; i < wedgeCount; i++) {
    fill(colors[i]);
    // Draw each wedge as a pie slice from center
    arc(
      0, 0,                  // centered at origin (already translated)
      wheelDiameter, wheelDiameter,
      i * step, (i + 1) * step,
      PIE                    // use PIE mode for wedge
    );
  }

  // Increment rotation angle for next frame
  rotationAngle += 0.01; // smaller = slower
}
Line-by-line explanation (11 lines)

🔧 Subcomponents:

for-loop Wedge Drawing Loop for (let i = 0; i < wedgeCount; i++) {

Iterates through the six colors and draws one pie-shaped wedge per color, dividing the full circle (TWO_PI) into equal slices.

background(0); // black background
Repaints the entire canvas black every frame, erasing the previous frame's wheel so the old rotation position doesn't leave a trail.
translate(width / 2, height / 2);
Moves the drawing origin (0,0) to the center of the canvas, so anything drawn afterward is positioned relative to the middle of the screen instead of the top-left corner.
rotate(rotationAngle);
Rotates the entire coordinate system by the current rotationAngle value. Because this happens before the wedges are drawn, it spins the whole wheel.
const wheelDiameter = min(width, height) * 0.6;
Calculates the wheel's diameter as 60% of whichever canvas dimension (width or height) is smaller, so the wheel always fits on screen regardless of window shape.
const colors = [ color(255, 0, 0), ... ];
Builds an array of six p5.Color objects, one for each wedge of the rainbow wheel, in the order they'll be drawn.
const wedgeCount = colors.length;
Stores how many wedges to draw by reading the length of the colors array, so the wheel automatically adjusts if colors are added or removed.
const step = TWO_PI / wedgeCount;
Divides a full circle (TWO_PI radians, or 360 degrees) evenly by the number of wedges, giving the angular width of each slice.
for (let i = 0; i < wedgeCount; i++) {
Loops once for every color in the array, using i to track which wedge is currently being drawn.
fill(colors[i]);
Sets the fill color for the upcoming shape to the current wedge's color from the array.
arc(0, 0, wheelDiameter, wheelDiameter, i * step, (i + 1) * step, PIE);
Draws one pie-shaped slice centered at the origin. The start angle is i * step and the end angle is (i + 1) * step, so each loop iteration draws the next slice around the circle. PIE mode connects the arc's ends back to the center, forming a wedge instead of just a curved line.
rotationAngle += 0.01; // smaller = slower
Increases the rotation angle by a small amount so that on the next frame, rotate() spins the wheel a bit further, producing continuous animated rotation.

windowResized()

windowResized() is a special p5.js function that's automatically called whenever the browser window is resized. Pairing it with resizeCanvas() is the standard way to keep a sketch responsive to different screen sizes.

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}
Line-by-line explanation (1 lines)
resizeCanvas(windowWidth, windowHeight);
Whenever the browser window changes size, this resizes the p5.js canvas to match the new window dimensions, keeping the sketch full-screen.

📦 Key Variables

rotationAngle number

Tracks the wheel's current rotation in radians. It starts at 0 and is incremented a tiny amount every frame inside draw(), which is what makes the wheel appear to spin continuously.

let rotationAngle = 0;

🔧 Potential Improvements (4)

Here are some ways this code could be enhanced:

PERFORMANCE draw()

The colors array of six p5.Color objects is recreated from scratch every single frame (60 times per second), even though the colors never change.

💡 Move the colors array declaration outside of draw() (e.g., into a global variable created in setup()) so the color objects are only created once instead of every frame.

BUG draw() - rotationAngle increment

The rotation speed is tied directly to frame count (0.01 radians per call to draw()), so the wheel will spin faster or slower depending on the viewer's frame rate or device performance rather than real elapsed time.

💡 Use deltaTime to make the rotation speed frame-rate independent, e.g. rotationAngle += 0.001 * deltaTime, so the animation looks the same speed on every device.

STYLE draw()

Magic numbers like 0.6 (wheel size) and 0.01 (rotation speed) are hardcoded inline, making them harder to find and tweak.

💡 Pull these into named constants near the top of the file, such as const WHEEL_SCALE = 0.6; and const SPIN_SPEED = 0.01;, so they're easier to locate and adjust.

FEATURE draw() / mousePressed()

The sketch has no interactivity - the wheel just spins at a fixed rate with no way for the viewer to change it.

💡 Add a mousePressed() or keyPressed() function that changes the rotation speed or reverses direction, or map mouseX to control the spin speed in real time for a more engaging experience.

🔄 Code Flow

Code flow showing setup, draw, windowresized

💡 Click on function names in the diagram to jump to their code

graph TD start[Start] --> setup[setup] setup --> draw[draw loop] draw --> background[background(0)] draw --> rotate[rotate(rotationAngle)] draw --> translate[translate(width/2, height/2)] draw --> wedge-loop[Wedge Drawing Loop] wedge-loop --> colorIteration[Iterate through colors] colorIteration --> drawWedge[draw pie-shaped wedge] drawWedge --> wedge-loop draw --> updateAngle[Update rotationAngle] updateAngle --> draw click setup href "#fn-setup" click draw href "#fn-draw" click wedge-loop href "#sub-wedge-loop" click colorIteration href "#sub-color-iteration" click drawWedge href "#sub-draw-wedge" click updateAngle href "#sub-update-angle" draw --> windowresized[windowResized] windowresized --> resizeCanvas[resizeCanvas(width, height)] click windowresized href "#fn-windowresized" click resizeCanvas href "#sub-resize-canvas"

❓ Frequently Asked Questions

What visual effect does the Spinning Rainbow Color Wheel create?

The sketch produces a mesmerizing rotating color wheel divided into six vibrant wedges, creating a hypnotic rainbow effect against a dark background.

Can users interact with the Spinning Rainbow Color Wheel sketch?

The sketch is not interactive; it continuously spins and displays the color wheel without user input.

What creative coding concepts are showcased in the Spinning Rainbow Color Wheel sketch?

This sketch demonstrates the use of p5.js to create dynamic visuals through rotation, color manipulation, and the drawing of arcs to form pie slices.

Preview

Spinning Rainbow Color Wheel - xelsed.ai - p5.js creative coding sketch preview
Sketch Preview
Code flow diagram showing the structure of Spinning Rainbow Color Wheel - xelsed.ai - Code flow showing setup, draw, windowresized
Code Flow Diagram