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.
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
.