Fill’r up please! The canvas msFillRule API
Up until now, when you create a filled shape using canvas path methods, your choice of how it looks when you use the fill method were limited to one choice: the nonzero fill rule.
With Internet Explorer 11, you now have two choices, nonzero and evenodd. Here’s how it works.
The fill rule impacts how a shape gets filled. When you create a shape with a path, nonzero and evenodd fill rules are algorithms that check whether a point is inside or outside the enclosed shape. To figure this out, the nonzero rule specifies that you pick a point in the shape, and draw a ray out to infinity (or at least outside the shape). Starting at the chosen point, and with a count of zero, you add a one each time the ray crosses a path that goes from left to right. If the path goes from right to left, you subtract a one. If the result is zero once the counting is complete, then the point is outside the path, otherwise it's inside.
Here’s a diagram that explains what we mean by right to left and left to right. The arrows show the direction of the lines.
ctx.moveTo(200, 110); ctx.lineTo(50, 110); ctx.lineTo(300, 310); ctx.lineTo(200, 10); ctx.lineTo(100, 310); ctx.lineTo(350, 110); ctx.lineTo(200, 110); ctx.stroke(); |
The evenodd rule says if you draw a ray from a point to infinity, count the number of path segments that the ray crosses. If the count is an odd number, then the point is inside the shape. If it's even, then the point is outside the shape. It doesn’t matter which way the paths are going.
This example shows the star getting filled in using the two different fill rules. By setting msFillRule, you can specify nonzero (the default), or evenodd.
<!DOCTYPE html>
< html>
< head>
<title>msFillRule example</title>
<meta />
</head>
< body>
<h1>Fill rule example</h1>
<h3>Click the button below to toggle between nonzero and evenodd fill rules. </h3>
<canvas id="MyCanvas" width="400" height="400">This browser or document mode doesn't support canvas</canvas>
< br />
<button id="myButton">Change</button>
<script>
document.getElementById("myButton").addEventListener("click", draw, false);
function draw() {
var canvas = document.getElementById("MyCanvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear area for repeated use
ctx.beginPath();
ctx.strokeStyle = "blue";
ctx.lineWidth = "5"
ctx.moveTo(200, 110);
ctx.lineTo(50, 110);
ctx.lineTo(300, 310);
ctx.lineTo(200, 10);
ctx.lineTo(100, 310);
ctx.lineTo(350, 110);
ctx.lineTo(200, 110);
ctx.stroke();
ctx.fillStyle = "yellow";
if (ctx.msFillRule == "nonzero") {
ctx.msFillRule = "evenodd";
document.getElementById("myButton").innerHTML = "Change to non-zero";
} else {
ctx.msFillRule = "nonzero";
document.getElementById("myButton").innerHTML = "Change to even-odd";
}
// ctx.fill();
}
}
draw();
</script>
</body>
< /html>
When you run this example, you can click the button to goggle back and forth between the two rules. You’ll see:
So give it a try. For now, as a prefixed API, it’s only available in Internet Explorer 11.