PEN:
var canvas = document.getElementById('c');
var ctx = canvas.getContext("2d");
var centerw = canvas.width/2;
var centerh = canvas.height/2;
var sq_w = 80;
//
ctx.beginPath();
//draw rectangle
ctx.rect(this.centerw-(sq_w/2), 0,sq_w, canvas.height);
//draw circle
ctx.arc(this.centerw, this.centerh, 185, 0, Math.PI * 2, true);
//fill
ctx.fill();
The shapes both draw but the intersection of the shapes is blank.
Looking to have one single, filled shape, but get the following result:[
REQUIREMENTS:
Cannot use CanvasRenderingContext2D.globalCompositeOperation
as I'm using that for something else; this needs to be used as a single shape so i can use the shape to ...clip().
Note: when using two rect() calls it works, and when using two arc() calls it works, but mixing them seems to cause an issue.
Seems like it should be easy but I'm stumped, missing something basic I think. Thanks!
PEN: https://codepen.io/jaredstanley/pen/gvmNye
var canvas = document.getElementById('c');
var ctx = canvas.getContext("2d");
var centerw = canvas.width/2;
var centerh = canvas.height/2;
var sq_w = 80;
//
ctx.beginPath();
//draw rectangle
ctx.rect(this.centerw-(sq_w/2), 0,sq_w, canvas.height);
//draw circle
ctx.arc(this.centerw, this.centerh, 185, 0, Math.PI * 2, true);
//fill
ctx.fill();
The shapes both draw but the intersection of the shapes is blank.
Looking to have one single, filled shape, but get the following result:[
REQUIREMENTS:
Cannot use CanvasRenderingContext2D.globalCompositeOperation
as I'm using that for something else; this needs to be used as a single shape so i can use the shape to ...clip().
Note: when using two rect() calls it works, and when using two arc() calls it works, but mixing them seems to cause an issue.
Seems like it should be easy but I'm stumped, missing something basic I think. Thanks!
Share Improve this question edited Feb 10, 2018 at 20:24 jared asked Feb 10, 2018 at 19:50 jaredjared 75210 silver badges19 bronze badges3 Answers
Reset to default 5Path-direction matters
Simply remove (or set to false
) the counter-clock wise flag on the arc()
method as this will otherwise define the path the "opposite" direction affecting the default non-zero winding algorithm used for filling:
//ctx.arc(this.centerw, this.centerh, 185, 0, Math.PI * 2, true); ->
ctx.arc(this.centerw, this.centerh, 185, 0, Math.PI * 2);
A More Close Look at "Non-Zero Winding"
According to the non-zero winding rule we would add up winding counted from a point from where a line is "sent out". For each line intersection of the point's line we check the crossing line's direction and give it +1 for one direction, -1 if the opposite direction, and add those together.
To illustrate:
For the illustration on the left we can see that the sum of the directions of the two first line intersections (if point is placed left and center on y) will be 0 ("zero") so no fill for the center section. This would also happen if a point sent a line from center top and down through the shape.
However, in the illustration on the right the sum is non-zero when we e to the inner section so it too bees filled.
Example: arc()
uses clockwise direction instead
var canvas = document.getElementById('c');
var ctx = canvas.getContext("2d");
var centerw = canvas.width/2;
var centerh = canvas.height/2;
var sq_w = 120;
//
ctx.beginPath();
//draw rectangle
ctx.rect(centerw-(sq_w/2), 0,sq_w, canvas.height);
//draw circle
ctx.moveTo(centerw + 185, centerh); // create new sub-path (is unrelated, see below)
ctx.arc(centerw, centerh, 185, 0, Math.PI * 2); // <- don't use the CCW flag
//fill
ctx.fill();
<canvas id="c" width="500" height="500"></canvas>
Unrelated but something to have in mind: you would also want to create a new sub-path for the arc to avoid risking a line from a corner of the rect going to the start-angle point on the arc. Simply add this line before adding the arc:
ctx.moveTo(centerw + 185, centerh);
ctx.arc(centerw, centerh, 185, 0, Math.PI * 2);
ctx.beginPath();
//draw rectangle
ctx.rect(this.centerw - (sq_w / 2), 0, sq_w, canvas.height);
ctx.fill();
//draw circle
ctx.beginPath();
ctx.arc(this.centerw, this.centerh, 185, 0, Math.PI * 2, true);
//fill
ctx.fill();
The result you see happens because the standard operation on a surface contained by crossed paths, is to ignore.
var canvas = document.getElementById('c');
var ctx = canvas.getContext("2d");
var centerw = canvas.width/2;
var centerh = canvas.height/2;
var sq_w = 80;
//draw rectangle
ctx.fillRect(this.centerw-(sq_w/2), 0,sq_w, canvas.height);
//draw circle
ctx.arc(this.centerw, this.centerh, 185, 0, Math.PI * 2, true);
//fill
ctx.fill();
<canvas id='c' height=500 width=500/>
The shapes need to be filled between the rounds. Or, in the code snippet, I changed ctx.rect to ctx.fillRect.
Another approach would be to begin a new path before the arc.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745441291a4627844.html
评论列表(0条)