Skip to content

Instantly share code, notes, and snippets.

@dereckmezquita
Created December 15, 2024 01:05
Show Gist options
  • Save dereckmezquita/1bff93267c115e271ebc23d7c40335e7 to your computer and use it in GitHub Desktop.
Save dereckmezquita/1bff93267c115e271ebc23d7c40335e7 to your computer and use it in GitHub Desktop.
Golden spiral (Fibonacci spiral) in JavaScript canvas
<!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>
@dereckmezquita
Copy link
Author

Screenshot 2024-12-14 at 19 06 34

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment