Search code examples
animationp5.jsmotionspiral

p5.js: make an animated spiral with line instead of ellipse?


I'm trying to animate a spiral using a line, but can only seem to get it to work using ellipses.

Does anyone know how to replace the ellipse() with line()?

here is the code:

var angle = 0.0;
var offset = 60;
var scalar = 10;
var speed = 0.05;

function setup() {
  createCanvas(600, 120);
  fill(0);
}

function draw() {
  var x = offset + cos(angle) * scalar;
  var y = offset + sin(angle) * scalar;
  ellipse( x, y, 2, 2);
  angle += speed;
  scalar += speed;
}

Solution

  • Assuming you would like to draw the entire spiral instantaneously using line segments, the you simply need a for loop that calculates the x and y coordinates for the current and next point in the spiral for some increment of change, and then draw lines between each pair of points. There are certainly numerous ways to write such a for loop, depending on what the constrains are (do you want a specific number of rings in your spiral? a specific number of degrees of rotation?), but importantly the bigger your increment of change the less smooth your spiral will look. Here is an example that uses the mouse position to determine the number of rings and the size of the change increments:

    function setup() {
      createCanvas(windowWidth, windowHeight);
      stroke(0);
      strokeWeight(4);
      textAlign(LEFT, TOP);
    }
    
    function draw() {
      background(255);
      
      // let the horizontal mouse position indicate the
      // size of the steps
      let speed = map(mouseX, 0, width, 0.01, 1, true);
    
      // let the vertical mouse position indicate the
      // total amount of rotation
      let maxRotation = map(mouseY, 0, height, TWO_PI, TWO_PI * 50, true);
      
      push();
      noStroke();
      fill('red');
      text(`Rings: ${(maxRotation / TWO_PI).toFixed(1)}, Speed: ${speed.toFixed(2)}`, 10, 10);
      pop();
      
      translate(width / 2, height / 2);
      
      let scalar = 10;
      if (speed <= 0) {
        console.error('cannot have <= 0 speed');
        return;
      }
      for (let angle = 0; angle < maxRotation; angle += speed, scalar += speed) {
        const x = cos(angle) * scalar;
        const y = sin(angle) * scalar;
        
        const x2 = cos(angle + speed) * (scalar + speed);
        const y2 = sin(angle + speed) * (scalar + speed);
        line(x, y, x2, y2);
      }
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>