Skip to content

Instantly share code, notes, and snippets.

@hugs
Created November 5, 2016 15:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hugs/bf0b2c2cd38d5f03e23a6bae0bc9abb1 to your computer and use it in GitHub Desktop.
Save hugs/bf0b2c2cd38d5f03e23a6bae0bc9abb1 to your computer and use it in GitHub Desktop.
Arc Examples
<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