Harshal Patil
Harshal Patil

Reputation: 20980

Should canvas fill() method be called before or after closing the path()?

I am unable to understand the behavior of the HTML Canvas fill method. By definition, it should fill current path or given path. However, I notice that fill method's behavior is same irrespective of where I put it i.e. before or after closing my path using closePath method. It still ends up filling my square drawn using Canvas path exactly same way.

function draw(context) {
  context.fillStyle = "#FF1010";

  context.beginPath();
  context.moveTo(0, 0);
  context.lineTo(100, 0);
  context.lineTo(100, 100);
  context.lineTo(0, 100);
  context.lineTo(0, 0);
  context.closePath();
  
  // Where should this be?
  context.fill();
}

So, what's the correct way to use the fill method.

Upvotes: 1

Views: 831

Answers (2)

Kaiido
Kaiido

Reputation: 136786

You don't need to call closePath() for filling the path, it's done automatically.
Enclosed subpaths* do matter for stroking, for instance a closed rect won't render the same stroke as an unclosed quad of lineTo:

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const path = new Path2D();
path.moveTo(20, 20);
path.lineTo(70, 20);
path.lineTo(70, 70);
path.lineTo(20, 70);
path.lineTo(20, 20);

ctx.lineWidth = 10;
ctx.stroke(path);
// closed path on the right
ctx.translate(80, 0);
path.closePath();
ctx.stroke(path);
<canvas></canvas>

But fill will treat both exactly the same:

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const path = new Path2D();
path.moveTo(20, 20);
path.lineTo(70, 20);
path.lineTo(70, 70);
path.lineTo(20, 70);
// only 3 lineto on the left
ctx.fill(path);
// 4 lineto in the center
ctx.translate(80, 0);
path.lineTo(20, 20);
ctx.fill(path); 
// closed path on the right
ctx.translate(80, 0);
path.closePath();
ctx.fill(path);
<canvas></canvas>

Also, to clear things up, since it seems that even answerers here are still confused, closePath() doesn't mean that your path declaration is over. It just means that the previous "sub-path" is enclosed; to make things easier than are, it's just a lineTo to the last moveTo point. If you keep adding path commands after that it will stil use that sub-path and will also start from that point.

To start a new path declaration you call ctx.beginPath().

.* a new subpath is created at each call to moveTo, closePath, rect and roundRect.

Upvotes: 4

obscure
obscure

Reputation: 12891

From a logical point of view the correct way would be to close the path before calling fill() simply because without a closed path, there won't be anything to fill. For convenience though your path gets closed automatically as soon as you call fill().

Remember though, that if you don't close the path at all and use additional drawing operations afterwards it will continue using the previous path.

Upvotes: 0

Related Questions