Skip to content

Instantly share code, notes, and snippets.

@akrolsmir
Created December 27, 2024 18:57
Show Gist options
  • Save akrolsmir/84fbe363e23b40a877cc0a9bf89dfe1e to your computer and use it in GitHub Desktop.
Save akrolsmir/84fbe363e23b40a877cc0a9bf89dfe1e to your computer and use it in GitHub Desktop.
christmas card but too much code to include
import { useState, useEffect } from 'react'
type Snowflake = {
id: number
x: number
y: number
size: number
speed: number
opacity: number
rotation: number
path: string
}
const generateSnowflakePath = (size: number) => {
const points = []
const pattern = Math.floor(Math.random() * 4) // 4 different pattern types
const branchCount = pattern === 3 ? 8 : 6 // Some snowflakes have 8 branches
const hasInnerBranches = Math.random() > 0.3
for (let i = 0; i < branchCount; i++) {
const angle = (i * 2 * Math.PI) / branchCount
const mainX = Math.cos(angle) * size
const mainY = Math.sin(angle) * size
points.push(`M 0 0 L ${mainX} ${mainY}`)
// Vary branch styles based on pattern
const branchLength = size * (0.2 + Math.random() * 0.4)
const branchAngle1 = angle + Math.PI / (3 + Math.random() * 3)
const branchAngle2 = angle - Math.PI / (3 + Math.random() * 3)
const midX = Math.cos(angle) * (size * 0.5)
const midY = Math.sin(angle) * (size * 0.5)
if (pattern === 0 || pattern === 2) {
points.push(`M ${midX} ${midY} L ${midX + Math.cos(branchAngle1) * branchLength} ${midY + Math.sin(branchAngle1) * branchLength}`)
points.push(`M ${midX} ${midY} L ${midX + Math.cos(branchAngle2) * branchLength} ${midY + Math.sin(branchAngle2) * branchLength}`)
}
if (hasInnerBranches && (pattern === 1 || pattern === 2)) {
const innerX = Math.cos(angle) * (size * 0.3)
const innerY = Math.sin(angle) * (size * 0.3)
points.push(`M ${innerX} ${innerY} L ${innerX + Math.cos(angle + Math.PI/3) * branchLength*0.5} ${innerY + Math.sin(angle + Math.PI/3) * branchLength*0.5}`)
points.push(`M ${innerX} ${innerY} L ${innerX + Math.cos(angle - Math.PI/3) * branchLength*0.5} ${innerY + Math.sin(angle - Math.PI/3) * branchLength*0.5}`)
}
}
return points.join(' ')
}
export default function Component() {
const [snowflakes, setSnowflakes] = useState<Snowflake[]>([])
useEffect(() => {
const createSnowflakes = () => {
const flakes: Snowflake[] = []
for (let i = 0; i < 150; i++) {
const size = Math.random() * 8 + 6
flakes.push({
id: i,
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
size: size,
speed: Math.random() * 2 + 1,
opacity: Math.random() * 0.8 + 0.5,
rotation: Math.random() * 360,
path: generateSnowflakePath(size / 2)
})
}
return flakes
}
let animationFrameId: number
const updateSnowflakes = () => {
setSnowflakes(prev => prev.map(flake => ({
...flake,
y: flake.y > window.innerHeight ? -10 : flake.y + flake.speed,
x: flake.x + Math.sin(flake.y / 30) * 0.3,
rotation: flake.rotation + 0.5
})))
animationFrameId = requestAnimationFrame(updateSnowflakes)
}
setSnowflakes(createSnowflakes())
updateSnowflakes()
return () => cancelAnimationFrame(animationFrameId)
}, [])
return (
<div className="min-h-screen bg-red-800 p-4 flex items-center justify-center">
{/* Snow overlay */}
<div className="fixed inset-0 pointer-events-none" style={{ zIndex: 0 }}>
{snowflakes.map(flake => (
<svg
key={flake.id}
className="absolute"
style={{
left: `${flake.x}px`,
top: `${flake.y}px`,
width: `${flake.size}px`,
height: `${flake.size}px`,
opacity: flake.opacity,
transform: `translateZ(0) rotate(${flake.rotation}deg)`,
filter: 'blur(0.3px)'
}}>
<path
d={flake.path}
stroke="white"
strokeWidth="1"
fill="none"
transform={`translate(${flake.size/2},${flake.size/2})`}
/>
</svg>
))}
</div>
<div className="relative w-full max-w-2xl bg-white rounded-lg shadow-xl overflow-hidden" style={{ zIndex: 1 }}>
{/* Card content */}
<div className="relative p-8 text-center">
<div className="text-red-800 font-bold text-4xl mb-4"
style={{ fontFamily: 'cursive' }}>
Merry Christmas
</div>
<div className="text-3xl text-green-700 mb-6"
style={{ fontFamily: 'cursive' }}>
from Austin, Rachel & baby Ada
</div>
{/* Retro border decoration */}
<div className="border-4 border-double border-red-800 p-6 mb-6">
<h2 className="text-2xl font-bold text-red-800 mb-4">
Our 2024 Highlights
</h2>
<div className="text-left space-y-3 text-gray-700">
<p>πŸŽ€ Welcomed our precious Ada into the world</p>
<p>🏠 Settled into our new home</p>
<p>✈️ Baby's first trip to visit grandparents</p>
<p>πŸŽ„ Ada's first Christmas!</p>
</div>
</div>
<div className="mt-8 text-2xl text-green-700"
style={{ fontFamily: 'cursive' }}>
Wishing you joy and peace in 2025!
</div>
{/* Retro decorative elements */}
<div className="absolute top-4 left-4">
<div className="text-4xl">🎁</div>
</div>
<div className="absolute top-4 right-4">
<div className="text-4xl">πŸŽ„</div>
</div>
<div className="absolute bottom-4 left-4">
<div className="text-4xl">β›„</div>
</div>
<div className="absolute bottom-4 right-4">
<div className="text-4xl">⭐</div>
</div>
</div>
</div>
</div>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment