fill a custom object defined by a path2d object

501 views Asked by At

I am trying to fill a path2d object of the HTML5 canvas.context.

I have drawn a custom path that is a bezier curve according to this site: https://javascript.info/bezier-curve

but am unable to get it to fill with a solid colour.

Here is some code in a jsfiddle to illustrate my problem. If I uncomment the line //this.ctx.stroke(this.p2d); then the outline of the bezier curve will be drawn, but I can't seem to fill the completed path.


constructor () {
    this.canv = document.getElementById('canv');
    this.ctx = this.canv.getContext('2d');
  this.ctx.beginPath();
  this.ctx.moveTo(160,350);
  this.ctx.restore();
  this.p2d = new Path2D();
    this.t = 0;
    this.currentPoint = [160,350];
  this.to = setInterval(() => this.plot(), 10, this.to);
}

plot(intid) {
      const p1x = 160;
      const p2x = 20;
      const p3x = 320;
      const p4x = 160;
      const p1y = 350;
      const p2y = 50;
      const p3y = 50;
      const p4y = 350;
      let t = this.t;
      let x = (((1 - t)*(1 - t)*(1 - t)) * p1x) + ((3 * ((1 - t) * (1 -t))) * (t * p2x)) + ((3 * ((1 - t) * (1 -t))) * (t * p3x)) + ((t * t * t) * p4x);
      let y = (((1 - t)*(1 - t)*(1 - t)) * p1y) + ((3 * ((1 - t) * (1 -t))) * (t * p2y)) + ((3 * ((1 - t) * (1 -t))) * (t * p3y)) + ((t * t * t) * p4y);
      this.t = t + 0.01;
      if (t <= 1.01) {

        //this.p2d.fillStyle = "#1000ff";
        this.p2d.moveTo(this.currentPoint[0], this.currentPoint[1]);
        this.p2d.lineTo(x, y);
        this.currentPoint[0] = x;
        this.currentPoint[1] = y;
        console.log(x + " " + y + " " + t)
      }
      else
      {
        //this.p2d.closePath();
        this.ctx.lineWidth = 2;
        this.ctx.strokeStyle = "blue";
        this.ctx.fillStyle = "blue";
        //this.ctx.stroke(this.p2d);
        this.ctx.fill(this.p2d, "evenodd");
        clearInterval(this.to);  
      }
  }
}

Window.cl = new clazz();

https://jsfiddle.net/9oL4xw1b/2/

ps. this is advanced math for me, so although my formula for calculating x and y is correct, it may not be optimised properly.

1

There are 1 answers

0
Helder Sepulveda On BEST ANSWER

Every time you move there will be nothing to fill...
All you are drawing at the end is lines with that technique, see the difference in the code below.

canv = document.getElementById('canv');
ctx = canv.getContext('2d');
ctx.fillStyle = "blue";

ctx.moveTo(10, 10);
ctx.lineTo(20, 40);
ctx.lineTo(99, 40);
ctx.lineTo(90, 30);

ctx.fill();
ctx.stroke();


ctx.moveTo(100, 10);
ctx.lineTo(120, 40);
ctx.moveTo(120, 40);
ctx.lineTo(200, 40);
ctx.moveTo(200, 40);
ctx.lineTo(190, 30);

ctx.fill();
ctx.stroke();
<canvas id="canv" width="500px" height="100px"></canvas>


So in your code just commenting the this.p2d.moveTo does it

class clazz {
  constructor() {
    this.canv = document.getElementById('canv');
    this.ctx = this.canv.getContext('2d');
    this.ctx.moveTo(160, 350);
    this.p2d = new Path2D();
    this.t = 0;
    this.currentPoint = [160, 350];
    this.to = setInterval(() => this.plot(), 5, this.to);
  }

  plot(intid) {
    const p1x = 160; const p2x = 20;
    const p3x = 320; const p4x = 160;
    const p1y = 350; const p2y = 50;
    const p3y = 50;  const p4y = 350;
    let t = this.t;
    let x = (((1 - t) * (1 - t) * (1 - t)) * p1x) + ((3 * ((1 - t) * (1 - t))) * (t * p2x)) + ((3 * ((1 - t) * (1 - t))) * (t * p3x)) + ((t * t * t) * p4x);
    let y = (((1 - t) * (1 - t) * (1 - t)) * p1y) + ((3 * ((1 - t) * (1 - t))) * (t * p2y)) + ((3 * ((1 - t) * (1 - t))) * (t * p3y)) + ((t * t * t) * p4y);
    this.t = t + 0.01;
    if (t <= 1.01) {
      //this.p2d.moveTo(this.currentPoint[0], this.currentPoint[1]);
      this.p2d.lineTo(x, y);
      this.ctx.stroke(this.p2d);
    } else {
      this.ctx.lineWidth = 2;
      this.ctx.strokeStyle = "blue";
      this.ctx.fillStyle = "blue";
      this.ctx.fill(this.p2d, "evenodd");
      clearInterval(this.to);
    }
  }
}

Window.cl = new clazz();
<canvas id="canv" width="500px" height="500px"></canvas>