Created
November 5, 2016 15:52
-
-
Save hugs/bf0b2c2cd38d5f03e23a6bae0bc9abb1 to your computer and use it in GitHub Desktop.
Arc Examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
margin: 30px; | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="tutorial" width="800" height="800"> | |
</canvas> | |
<script> | |
// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc | |
// https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-arc | |
var width = 800; | |
var height = 800; | |
var canvas = document.getElementById('tutorial'); | |
var ctx = canvas.getContext('2d'); | |
ctx.scale(1,1); | |
ctx.font = "14px sans-serif"; | |
var tau = Math.TAU = 2*Math.PI; | |
function arcExample(xOffset, yOffset, radius, start, end, directionLabel) { | |
var startAngle = eval(start); | |
var endAngle = eval(end); | |
var direction = directionLabel === 'clockwise' ? false : true; | |
var directionArg = direction === false ? '' : ', true' | |
var description; | |
if (startAngle > endAngle) { | |
description = 'startAngle > endAngle, ' | |
} else { | |
description = 'startAngle < endAngle, ' | |
} | |
// Draw UI | |
drawAxes(xOffset,yOffset); | |
drawText(description + directionLabel, xOffset, yOffset, true); | |
drawText('arc(' + | |
xOffset + ', ' + | |
yOffset + ', ' + | |
radius + ', ' + | |
start + ', ' + | |
end + | |
directionArg + ')', | |
xOffset, yOffset+20); | |
drawArcOutline(xOffset, yOffset, radius, startAngle, endAngle, direction); | |
// Draw the arc | |
arc(xOffset, yOffset, radius, startAngle, endAngle, direction ); | |
} | |
function drawAxes(xOffset, yOffset) { | |
lineLength = 140; | |
ctx.beginPath(); | |
ctx.moveTo(xOffset, yOffset + lineLength/2); | |
ctx.lineTo(xOffset, yOffset - lineLength/2); | |
ctx.strokeStyle = 'LightGrey'; | |
ctx.stroke(); | |
ctx.beginPath(); | |
ctx.moveTo(xOffset - lineLength/2, yOffset); | |
ctx.lineTo(xOffset + lineLength/2, yOffset); | |
ctx.strokeStyle = 'LightGrey'; | |
ctx.stroke(); | |
ctx.font = "16px serif"; | |
// Tau | |
ctx.fillText('0, τ', xOffset+75, yOffset+5); | |
ctx.fillText('τ/2', xOffset-90, yOffset+5); | |
ctx.fillText('τ/4', xOffset-10, yOffset+85); | |
ctx.fillText('3τ/4', xOffset-15, yOffset-80); | |
} | |
function drawText (text, xOffset, yOffset, bold) { | |
if (typeof(bold) !== "undefined") { | |
ctx.font = "bold 14px sans-serif"; | |
} else { | |
ctx.font = "14px sans-serif"; | |
} | |
ctx.fillText(text, xOffset-100, yOffset+120); | |
} | |
function drawArcOutline(centerX, centerY, radius, startAngle, endAngle, anticlockwise) { | |
// Draw path outline | |
ctx.beginPath(); | |
ctx.strokeStyle = 'LightGrey'; | |
ctx.arc(centerX, centerY, radius, startAngle, endAngle, anticlockwise); | |
ctx.stroke(); | |
ctx.strokeStyle = 'Black'; | |
} | |
function areValid(arguments) { | |
// Check for correct number of arguments | |
if (arguments.length < 5) { return false; } | |
if (arguments.length > 6) { return false; } | |
// If any of the arguments are infinite or NaN, then abort. | |
for (var parameter in arguments) { | |
if (!isFinite(arguments[parameter])) { return false; } | |
if (isNaN(arguments[parameter])) { return false; } | |
} | |
return true; | |
} | |
function calcPoint(cX, cY, r, radian) { | |
var pointX = cX + r * Math.cos(radian); | |
var pointY = cY + r * Math.sin(radian); | |
return {x: pointX, y: pointY} | |
} | |
function plotPoint(x, y, pointType) { | |
var w = 3 | |
var h = 3; | |
var xOffset = w/2; | |
var yOffset = h/2; | |
ctx.fillStyle = "Black"; | |
if (typeof(pointType) !== "undefined") { | |
w = h = 12; | |
xOffset = yOffset = w/2; | |
if (pointType === "start") { | |
ctx.fillStyle = "LightGreen"; | |
ctx.beginPath(); | |
ctx.arc(x,y,8,0,tau); | |
ctx.fill(); | |
ctx.strokeStyle = "Black"; | |
ctx.stroke(); | |
ctx.fillStyle = "Black"; | |
return; | |
} else if (pointType === "end") { | |
ctx.fillStyle = "Red"; | |
} | |
} | |
ctx.fillRect(x-xOffset,y-yOffset,w,h); | |
ctx.fillStyle = "Black"; | |
} | |
function arc(centerX, centerY, radius, startAngle, endAngle, anticlockwise) { | |
if (!areValid(arguments)) return; | |
// Test if anticlockwise was given. If not, set to false. | |
if (typeof(anticlockwise) === "undefined") { | |
var anticlockwise = false; | |
} else { | |
// Abort if not boolean | |
if (typeof(anticlockwise) !== "boolean") { | |
return; | |
} | |
} | |
// Modulo angles into range | |
startAngle = startAngle % tau; | |
endAngle = endAngle % tau; | |
var clockwise = !anticlockwise; | |
if (clockwise === true) { | |
// If needed, offset startAngle by one full turn so the loop works | |
if (startAngle > endAngle) { | |
startAngle -= tau; | |
} | |
// Plot starting point | |
var point = calcPoint(centerX, centerY, radius, startAngle); | |
plotPoint(point.x,point.y, 'start'); | |
// Plot all path points | |
var counter = 0; | |
for (var radian = startAngle; radian <= endAngle; radian += .05) { | |
var point = calcPoint(centerX, centerY, radius, radian);; | |
//plotPoint(point.x,point.y); | |
setTimeout(plotPoint, counter, point.x, point.y); | |
counter += 20; | |
} | |
// Plot ending point | |
plotPoint(point.x,point.y, 'end'); | |
} else { | |
// If needed, offset startAngle by one full turn so the loop works | |
if (startAngle < endAngle) { | |
startAngle += tau; | |
} | |
// Plot starting point | |
var point = calcPoint(centerX, centerY, radius, startAngle); | |
plotPoint(point.x,point.y, 'start'); | |
// Plot all path points | |
var counter = 0; | |
for (var radian = startAngle; radian >= endAngle; radian -= .05) { | |
var point = calcPoint(centerX, centerY, radius, radian); | |
setTimeout(plotPoint, counter, point.x, point.y); | |
counter += 20; | |
} | |
// Plot ending point | |
plotPoint(point.x,point.y, 'end'); | |
} | |
} | |
//----------------------------------------------------- | |
// Example #1: startAngle > endAngle, clockwise | |
arcExample(100, 100, 50, 'tau/2', 'tau/4', 'clockwise'); | |
// Example #2: startAngle > endAngle, anticlockwise | |
arcExample(400, 100, 50, 'tau/2', 'tau/4', 'anticlockwise'); | |
// Example #3: startAngle < endAngle, clockwise | |
arcExample(100, 400, 50, 'tau/4', 'tau/2', 'clockwise'); | |
// Example #4: startAngle < endAngle, anticlockwise | |
arcExample(400, 400, 50, 'tau/4', 'tau/2', 'anticlockwise'); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment