Created
December 15, 2024 01:05
-
-
Save dereckmezquita/1bff93267c115e271ebc23d7c40335e7 to your computer and use it in GitHub Desktop.
Golden spiral (Fibonacci spiral) in JavaScript canvas
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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Golden Spiral Demo</title> | |
<style> | |
body { | |
margin: 0; | |
padding: 0; | |
background: #ffffff; /* White background */ | |
} | |
canvas { | |
display: block; | |
margin: 0 auto; | |
background: #ffffff; /* White background for the canvas */ | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="spiralCanvas" width="800" height="600"></canvas> | |
<script> | |
/** | |
* Draws the golden spiral on the given canvas context. | |
* We use a logarithmic spiral defined by the formula: | |
* r(θ) = a * φ^(θ/(π/2)) | |
* where φ (phi) is the golden ratio. | |
* | |
* For simplicity, we step through θ (in radians) and | |
* convert polar coordinates (r, θ) to Cartesian (x, y). | |
*/ | |
/** | |
* Returns the golden ratio. | |
* φ = (1 + √5) / 2 | |
*/ | |
function getGoldenRatio() { | |
return (1 + Math.sqrt(5)) / 2; | |
} | |
/** | |
* Given a polar coordinate (r, θ), returns the Cartesian coordinate (x, y). | |
* Assumes (0,0) at top-left, so we’ll recenter later. | |
*/ | |
function polarToCartesian(r, theta) { | |
const x = r * Math.cos(theta); | |
const y = r * Math.sin(theta); | |
return { x: x, y: y }; | |
} | |
/** | |
* Draw the golden spiral. | |
* @param {CanvasRenderingContext2D} ctx - The 2D drawing context. | |
* @param {number} centerX - The x-coordinate of the centre point. | |
* @param {number} centerY - The y-coordinate of the centre point. | |
* @param {number} startTheta - Starting angle in radians. | |
* @param {number} endTheta - Ending angle in radians. | |
* @param {number} a - Scaling factor for the spiral. | |
*/ | |
function drawGoldenSpiral(ctx, centerX, centerY, startTheta, endTheta, a) { | |
const phi = getGoldenRatio(); | |
// Line style | |
ctx.strokeStyle = "#000000"; // Black line | |
ctx.lineWidth = 3; // Slightly thick line | |
ctx.beginPath(); | |
// Move to the starting point of the spiral | |
let startR = a * Math.pow(phi, (startTheta / (Math.PI / 2))); | |
let startPoint = polarToCartesian(startR, startTheta); | |
ctx.moveTo(centerX + startPoint.x, centerY + startPoint.y); | |
// Step through θ and plot the spiral | |
// Smaller step size results in a smoother curve. | |
const step = 0.01; | |
for (let theta = startTheta; theta <= endTheta; theta += step) { | |
const r = a * Math.pow(phi, (theta / (Math.PI / 2))); | |
const point = polarToCartesian(r, theta); | |
ctx.lineTo(centerX + point.x, centerY + point.y); | |
} | |
ctx.stroke(); | |
} | |
/** | |
* Initialise the canvas and draw the spiral. | |
* This function sets up the canvas and calls the | |
* draw function with chosen parameters. | |
*/ | |
function init() { | |
const canvas = document.getElementById("spiralCanvas"); | |
const ctx = canvas.getContext("2d"); | |
// Clear the canvas (white background is by default set in CSS) | |
ctx.clearRect(0, 0, canvas.width, canvas.height); | |
// Centre of the canvas | |
const centerX = canvas.width / 2; | |
const centerY = canvas.height / 2; | |
// Draw a portion of the spiral - | |
// For demonstration, we draw from a small negative angle | |
// (to start close to center) and outwards. | |
const startTheta = -2 * Math.PI; // Start angle (radians) | |
const endTheta = 4 * Math.PI; // End angle (radians) | |
const a = 5; // Spiral scale factor | |
drawGoldenSpiral(ctx, centerX, centerY, startTheta, endTheta, a); | |
} | |
// Once the page loads, run init() | |
window.onload = init; | |
</script> | |
</body> | |
</html> |
Author
dereckmezquita
commented
Dec 15, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment