timerprocessingdrawingp5.jsbrush

Fixed Distance Brush with Timer in P5js


I'm quite new at this, but I'm attempting to create a fixed distance brush in P5 where the size of the brush gets bigger/wider overtime (using a timer)

This is what the code looks like right now

let path;
let timeLimit = 30;


function setup() {
  createCanvas(800, 500);
  path = new Path();
}

function draw() {
  background(225);
  path.display();
  path.addPoint(mouseX, mouseY);
}

class Path {
  constructor() {
    this.pts = [];
    this.angles = [];
    this.size = 30;
  }

  get lastPt() {
    return this.pts[this.pts.length - 1];
  }

  addPoint(x, y) {
    if (this.pts.length < 1) {
      this.pts.push(new p5.Vector(x, y));
      return;
    }

    const nextPt = new p5.Vector(x, y);
    let d = p5.Vector.dist(nextPt, this.lastPt);

    while (d > this.size) {
  
      const diff = p5.Vector.sub(nextPt, this.lastPt);
      diff.normalize();
      diff.mult(2);
      this.pts.push(p5.Vector.add(this.lastPt, diff));
      this.angles.push(diff.heading());
      d -= this.size;
    }
  }

  display() {
  
let r = map( frameCount, 0, timeLimit, 1, 20);
    
    rectMode(CENTER);
    for (let i = 1; i < this.pts.length; i++) {
      const prev = this.pts[i - 1];
      const next = this.pts[i];
      const diff = p5.Vector.sub(next, prev);
      diff.mult(0.1);
      push();
      translate(prev.x + diff.x, prev.y + diff.y);
      fill(255, 0, 0, 75);
      line(0, 0,(r), 1);
      pop();
    }
  }
}
<!DOCTYPE html>
<html lang="en"><head><script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/addons/p5.sound.min.js"></script><link rel="stylesheet" type="text/css" href="style.css"><meta charset="utf-8" /></head><body><script src="sketch.js"></script></body>
</html>

But the problem is that, all of the lines (including previously drawn ones) expands overtime , it doesn't expand gradually.

The image below illustrates what I want to achieve with the brush & timer function enter image description here

Any help/insight on how I could achieve this would be very much appreciated, thank you! :)


Solution

  • You are currently calculating r for each point when drawing the path. Since you redraw the entire path each frame all of the segments will grow. To prevent this you need to make r something that you calculate when you are adding points and include it in the data structure for the path.

    let path;
    let timeLimit = 30;
    
    
    function setup() {
      createCanvas(800, 500);
      path = new Path();
    }
    
    function draw() {
      background(225);
      path.display();
      path.addPoint(mouseX, mouseY);
    }
    
    class Path {
      constructor() {
        this.pts = [];
        this.angles = [];
        this.size = 30;
      }
    
      get lastPt() {
        return this.pts[this.pts.length - 1];
      }
    
      addPoint(x, y) {
        // The fundamental issue was calculating "r" while displaying the line,
        // instead of while drawing it. In order to set the width of the brush
        // as the path is drawn you need to calculate this here and store it
        // in the pts list along with the position (you could also use a
        // a separate array as you have done for angles).
        let r = map(frameCount, 0, timeLimit, 1, 20);
    
        if (this.pts.length < 1) {
          this.pts.push({ pos: new p5.Vector(x, y), r });
          return;
        }
    
        const nextPt = new p5.Vector(x, y);
        let d = p5.Vector.dist(nextPt, this.lastPt.pos);
    
        while (d > this.size) {
          const diff = p5.Vector.sub(nextPt, this.lastPt.pos);
          diff.normalize();
          diff.mult(2);
          this.pts.push({ pos: p5.Vector.add(this.lastPt.pos, diff), r });
          this.angles.push(diff.heading());
          d -= this.size;
        }
      }
    
      display() {
    
        // rectMode(CENTER);
        for (let i = 1; i < this.pts.length; i++) {
          const prev = this.pts[i - 1];
          const next = this.pts[i];
          const diff = p5.Vector.sub(next.pos, prev.pos);
          diff.mult(0.1);
          push();
          translate(prev.pos.x + diff.x, prev.pos.y + diff.y);
          fill(255, 0, 0, 75);
          line(0, 0, prev.r, 0);
          pop();
        }
      }
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>