Last active
August 18, 2023 23:42
-
-
Save r-i-c-h/40b101a8a322e4b132dd440f5322d532 to your computer and use it in GitHub Desktop.
HTML Canvas Shape Drawing Functions
This file contains 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
/*** Canvas Shape Drawing Functions ***/ | |
// 1. drawStar() - Draw an n-pointed Star w/controls for outer and inner radii - [can make sorta-polygons too] | |
// 2. drawCircle() - Draw a circle (ctx.arc() wrapper) | |
// 3A. drawPoly1() - Draw an n-sided Polygon | |
// 3B. drawPoly2() - Draw an n-sided Polygon | |
// 3C. drawPoly3() - Draw an n-sided Polygon (controls for initial Rotation in Radians) | |
/* Assume the following setup: */ | |
const canvas = document.getElementById('canvas1'); | |
const ctx = canvas.getContext('2d'); | |
canvas.width = canvas.clientWidth; // correct for screen distortion | |
canvas.height = canvas.clientHeight; // correct for screen distortion | |
/* 1. Draw an N-pointed Star with control of outer and inner radii: */ | |
function drawStar({ cx = 0, cy = 0, numPoints = 5, outerRadius = 100, innerRadius = 50, | |
lineWidth = 1, stroke = '#FFF', fill = 'transparent' } = {}) { | |
let rotationBase = Math.PI / 2 * 3; | |
const rotationIncrement = Math.PI / numPoints; | |
// set Visual properties | |
ctx.lineWidth = lineWidth; | |
ctx.strokeStyle = stroke; | |
ctx.fillStyle = fill; | |
ctx.beginPath(); | |
ctx.moveTo(cx, cy - outerRadius); // move to top | |
for (i = 0; i < numPoints; i++) { | |
// x = cx + Math.cos(rotationBase) * outerRadius; | |
// y = cy + Math.sin(rotationBase) * outerRadius; | |
ctx.lineTo( | |
(cx + Math.cos(rotationBase) * outerRadius), | |
(cy + Math.sin(rotationBase) * outerRadius) | |
); | |
rotationBase += rotationIncrement; | |
// x = cx + Math.cos(rotationBase) * innerRadius; | |
// y = cy + Math.sin(rotationBase) * innerRadius; | |
ctx.lineTo( | |
(cx + Math.cos(rotationBase) * innerRadius), | |
(cy + Math.sin(rotationBase) * innerRadius) | |
); | |
rotationBase += rotationIncrement; | |
} | |
ctx.lineTo(cx, cy - outerRadius); // back to start | |
ctx.closePath(); | |
// add the outline | |
ctx.stroke(); | |
// add the fill | |
ctx.fill(); | |
} | |
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ | |
// 2. Draw a Circle. Really just `context.arc()` | |
function drawCircle({ cx = 0, cy = 0, radius = 50, strokeColor = '#000', strokeWidth = 2, fill = 'transparent' } = {}) { | |
// start the path | |
ctx.beginPath(); | |
// plot out the path | |
ctx.arc(cx, cy, radius, 0, 2 * Math.PI); | |
// Stroke & Fill: | |
ctx.lineWidth = strokeWidth; | |
ctx.strokeStyle = strokeColor; | |
ctx.fillStyle = fill; | |
ctx.stroke(); | |
ctx.fill(); | |
}; | |
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ | |
/*** --- Three Different Tweaks on drawing an N-gon Polygon --- ***/ | |
// --- VERSION A: --- // | |
function drawPoly1({ cx = 200, cy = 200, numSides = 3, radius = 100, lineWidth = 1, stroke = '#FFFFFF', fill = 'transparent' } = {}) { | |
// set Visual properties | |
ctx.lineWidth = lineWidth; | |
ctx.strokeStyle = stroke; | |
ctx.fillStyle = fill; | |
// start the path | |
ctx.beginPath(); | |
// move to the first point (at "3 o'clock" position) | |
ctx.moveTo(cx + radius, cy + 0); | |
// determine angle of each pie slice based on number of sides | |
const angle = 2 * Math.PI / numSides; | |
// for each side, go to a corner. | |
for (var i = 1; i <= numSides; i++) { | |
// get the current angle based on where we are in the loop | |
let currentAngle = i * angle; | |
// use cosine to get horizontal coordinate | |
let x = cx + radius * Math.cos(currentAngle); | |
// use sin to get vertical coordinate | |
let y = cy + radius * Math.sin(currentAngle); | |
// go to this point next | |
ctx.lineTo(x, y); | |
} | |
// add the outline | |
ctx.stroke(); | |
// add the fill | |
ctx.fill(); | |
}; | |
// ----- VERSION B: ----- // | |
function drawPoly2({ cx = 200, cy = 200, numSides = 5, radius = 100, | |
lineWidth = 1, stroke = '#FFFFFF', fill = 'transparent' } = {}){ | |
if (numSides < 3){ return } | |
const angleIncrement = Math.PI / (numSides/2); | |
let rotationBase = Math.PI / 2 * 3; | |
// set Visual properties | |
ctx.lineWidth = lineWidth; | |
ctx.strokeStyle = stroke; | |
ctx.fillStyle = fill; | |
ctx.beginPath(); | |
ctx.moveTo(cx, cy - radius); // move to top | |
for (i = 0; i < numSides; i++) { | |
ctx.lineTo( | |
(cx + Math.cos(rotationBase) * radius), | |
(cy + Math.sin(rotationBase) * radius) | |
); | |
rotationBase += angleIncrement; | |
} | |
ctx.lineTo(cx, cy - radius); // back to start | |
ctx.closePath(); | |
ctx.stroke(); | |
ctx.fill(); | |
} | |
// ---- VERSION C: ---- // | |
function drawPoly3({cx = 200, cy = 200, numSides = 5, radius = 100, initialRotationInRAD = Math.PI * 1.5} = {}) { | |
if (numSides < 3) return; | |
const angle = (Math.PI * 2)/numSides; | |
ctx.save() | |
ctx.beginPath(); | |
ctx.translate( cx, cy ); | |
ctx.rotate(initialRotationInRAD); // MUST BE IN RADIANS, aka Math.PI * ___ | |
ctx.moveTo( radius, 0 ); | |
for (var i = 1; i < numSides; i++) { | |
ctx.lineTo( radius * Math.cos(i * angle), radius * Math.sin(i * angle)); | |
} | |
ctx.closePath(); | |
ctx.stroke() | |
ctx.restore() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment