The Fill Rule Demo
|
|
|
|
|
The HTML file:
<h1>The Fill Rule Demo</h1>
<table>
<tr><td>
<canvas id="rule" style="border:1px solid #000000;" width=200 height=200> </td><td>
<table>
<tr></td>
<label for="fillSelect">Select a Fill Style</label>
<select id="fillSelect" >
<option value="none">No Fill</option>
<option value="evenodd">Even Odd</option>
<option value="nonzero">Non-Zero</option>
</select>
</td></tr> <tr><td>
<label for="dataSelect">Select a Dataset</label>
<select id="dataSelect" >
<option value="ll">Line Loop</option>
<option value="bd">Broken Diamond</option>
</select>
</td></tr>
</table>
</tr></td>
</table>
<script src="winding.js"> </script>
"use strict"
const ruleCTX = document.getElementById("rule").getContext("2d")
const ruleWidth = document.getElementById("rule").width
const ruleHeight = document.getElementById("rule").height
const fillSelect = document.getElementById("fillSelect")
fillSelect.addEventListener("change", RedoFill)
const dataSelect = document.getElementById("dataSelect")
dataSelect.addEventListener("change", ChangeDataset)
const points1 = [[80,20], [80,180], [180,180], [180,60], [20,60], [20,160],
[60,160], [60,110], [160,110], [160,140], [120,140],
[120,20], [80,20]]
const points2 = [[100,20], [180,100], [20,130], [100,100],
[180,180], [20,100], [100,20]]
let arrows = true
let points = points1
function ChangeDataset() {
switch(dataSelect.value) {
case 'll':
points = points1
arrows = true
break;
case 'bd':
points = points2
arrows = true
break;
}
RedoFill()
}
function RedoFill() {
switch(fillSelect.value) {
case "none":
DrawShape('nonzero', false)
break
case "evenodd":
DrawShape('evenodd')
break
case "nonzero":
DrawShape('nonzero')
break
}
}
// note this is broken, we will fix it later.
// it only really works for horizontal and vertical lines.
// I added the other shape too late to fix it.
function DrawArrow(a,b) {
let x1 = a[0]
let y1 = a[1]
let x2 = b[0]
let y2 = b[1]
let mpx = (x1+x2)/2
let mpy = (y1+y2)/2
let dx = 5
let dy = 5
let tmpStyle = ruleCTX.strokeStyle
ruleCTX.strokeStyle = "red"
ruleCTX.beginPath()
if (x1 == x2 ) {
if(y1 < y2) {
dy = -5
}
ruleCTX.moveTo(mpx-dx, mpy+dy)
ruleCTX.lineTo(mpx, mpy)
ruleCTX.lineTo(mpx+dx, mpy+dy)
} else {
if (x1 < x2) {
dx = -5
}
ruleCTX.moveTo(mpx+dx, mpy-dy)
ruleCTX.lineTo(mpx, mpy)
ruleCTX.lineTo(mpx+dx, mpy+dy)
}
ruleCTX.stroke()
ruleCTX.strokeStyle = tmpStyle
}
function DrawShape(rule, filled = true) {
let i;
ruleCTX.fillStyle = "white"
ruleCTX.fillRect(0,0, ruleWidth, ruleHeight)
ruleCTX.fillStyle = "green"
ruleCTX.beginPath()
ruleCTX.moveTo(points[0][0], points[0][1])
for(i=1;i<points.length; ++i) {
ruleCTX.lineTo(points[i][0], points[i][1])
}
if (filled) {
ruleCTX.fill(rule)
}
ruleCTX.stroke()
if (arrows) {
for(i = 0; i < points.length-1; ++i) {
DrawArrow(points[i], points[i+1])
}
}
}
DrawShape('nonzero', false)