Reputation: 20980
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
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
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