-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b3fc65d
commit eaab0dc
Showing
1 changed file
with
116 additions
and
0 deletions.
There are no files selected for viewing
116 changes: 116 additions & 0 deletions
116
client/src/app/blog/posts/20241214_new-blog-feature-canvases.mdx
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
--- | ||
title: "New blog feature: canvases" | ||
blurb: "Circus bitch world" | ||
coverImage: 205 | ||
author: "Dereck Mezquita" | ||
date: 2024-12-14 | ||
tags: [programming, javascript, mathematics, blog, website, next, react, nextjs, reactjs] | ||
published: true | ||
comments: true | ||
--- | ||
|
||
## Golden Spiral Demo (Smaller Canvas) | ||
|
||
<CanvasWithJs | ||
code={` | ||
// Fill entire canvas with white | ||
ctx.fillStyle = '#ffffff'; | ||
ctx.fillRect(0, 0, canvas.width, canvas.height); | ||
function getGoldenRatio() { | ||
return (1 + Math.sqrt(5)) / 2; | ||
} | ||
function polarToCartesian(r, theta) { | ||
return { | ||
x: r * Math.cos(theta), | ||
y: r * Math.sin(theta) | ||
}; | ||
} | ||
function drawGoldenSpiral(ctx, centerX, centerY, startTheta, endTheta, a) { | ||
const phi = getGoldenRatio(); | ||
ctx.strokeStyle = '#000000'; | ||
ctx.lineWidth = 3; | ||
ctx.beginPath(); | ||
let startR = a * Math.pow(phi, (startTheta / (Math.PI / 2))); | ||
let startPoint = polarToCartesian(startR, startTheta); | ||
ctx.moveTo(centerX + startPoint.x, centerY + startPoint.y); | ||
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(); | ||
} | ||
const centerX = canvas.width / 2; | ||
const centerY = canvas.height / 2; | ||
const startTheta = -2 * Math.PI; | ||
const endTheta = 4 * Math.PI; | ||
const a = 5; | ||
drawGoldenSpiral(ctx, centerX, centerY, startTheta, endTheta, a); | ||
`} | ||
width={500} | ||
height={400} | ||
/> | ||
## Fractal Demo: Sierpinski Triangle | ||
|
||
The Sierpinski Triangle is a classic fractal formed by repeatedly subdividing a triangle into smaller triangles and removing the central one. We'll implement a simple recursive approach to draw it. | ||
|
||
<CanvasWithJs code={` | ||
// Fill the canvas with white | ||
ctx.fillStyle = '#ffffff'; | ||
ctx.fillRect(0, 0, canvas.width, canvas.height); | ||
// Draw a filled triangle | ||
function drawTriangle(ctx, x1, y1, x2, y2, x3, y3, color) { | ||
ctx.fillStyle = color; | ||
ctx.beginPath(); | ||
ctx.moveTo(x1, y1); | ||
ctx.lineTo(x2, y2); | ||
ctx.lineTo(x3, y3); | ||
ctx.closePath(); | ||
ctx.fill(); | ||
} | ||
// Recursive Sierpinski function | ||
function sierpinski(ctx, x1, y1, x2, y2, x3, y3, depth) { | ||
if (depth === 0) { | ||
drawTriangle(ctx, x1, y1, x2, y2, x3, y3, '#000000'); | ||
return; | ||
} | ||
// Midpoints of each side | ||
const x12 = (x1 + x2) / 2; | ||
const y12 = (y1 + y2) / 2; | ||
const x23 = (x2 + x3) / 2; | ||
const y23 = (y2 + y3) / 2; | ||
const x31 = (x3 + x1) / 2; | ||
const y31 = (y3 + y1) / 2; | ||
// Recursively draw smaller triangles | ||
sierpinski(ctx, x1, y1, x12, y12, x31, y31, depth - 1); | ||
sierpinski(ctx, x12, y12, x2, y2, x23, y23, depth - 1); | ||
sierpinski(ctx, x31, y31, x23, y23, x3, y3, depth - 1); | ||
} | ||
const width = canvas.width; | ||
const height = canvas.height; | ||
// Coordinates of a large upright triangle that fits the canvas | ||
const x1 = width / 2; | ||
const y1 = 0; | ||
const x2 = 0; | ||
const y2 = height; | ||
const x3 = width; | ||
const y3 = height; | ||
// Depth controls how many times we subdivide | ||
const depth = 6; | ||
sierpinski(ctx, x1, y1, x2, y2, x3, y3, depth); | ||
`} /> |