You have 2 options for drawing holes with an HTML5 canvas.
Choice 1:
Draw the outer shape and inner shape in different measures.
The outer form is clockwise and the inner form is counterclockwise.
Or the outer form is clockwise and the inner form is counterclockwise.
ctx.beginPath(); //outer shape, clockwise ctx.moveTo(100,20); ctx.lineTo(200,200); ctx.lineTo(20,200); ctx.closePath(); //inner shape (hole), counter-clockwise ctx.moveTo(100,100); ctx.lineTo(70,170); ctx.lineTo(140,170); ctx.closePath(); //fill ctx.fillStyle = "#FF0000"; ctx.fill();
Itβs a little pain to determine the direction in which the form is drawn when coding.
If you need to determine if there is a series of dots clockwise or not, here is a nice function:
function isClockwise(dots){ var sum = 0; for(var i=1, n=dots.length; i<n; i++){ sum += (dots[i][0] - dots[i-1][0]) * (dots[i][1] + dots[i-1][1]); } sum += (dots[0][0] - dots[n-1][0]) * (dots[0][1] + dots[n-1][1]); return sum < 0; } console.log(isClockwise([[100,20], [200,200], [20,200]]));
If your points are clockwise, but you need counterclockwise, .reverse () is your array of points.
var dots = [[100,20], [200,200], [20,200]]; dots.reverse();
Choice 2:
Use the 'evenodd' fill rule, draw your shapes in any direction.
This method is much simpler than choice 1.
see the fill () method API :
void ctx.fill(); void ctx.fill(fillRule); void ctx.fill(path, fillRule);
fillRule can be nonzero or evenodd
nonzero: non-zero winding rule, which is the default standard.
"evenodd": even winding rule.
ctx.beginPath(); //outer shape, any direction, this sample is clockwise ctx.moveTo(100,20); ctx.lineTo(200,200); ctx.lineTo(20,200); ctx.closePath(); //inner shape (hole), any direction, this sample is clockwise ctx.moveTo(100,100); ctx.lineTo(140,170); ctx.lineTo(70,170); ctx.closePath(); //fill ctx.fillStyle = "#FF0000"; ctx.mozFillRule = 'evenodd'; //for old firefox 1~30 ctx.fill('evenodd'); //for firefox 31+, IE 11+, chrome
