Skip to content

Instantly share code, notes, and snippets.

@zpuckeridge
Created November 20, 2023 06:10
Show Gist options
  • Select an option

  • Save zpuckeridge/577e84edec1e58c183b82c74df8830bb to your computer and use it in GitHub Desktop.

Select an option

Save zpuckeridge/577e84edec1e58c183b82c74df8830bb to your computer and use it in GitHub Desktop.
Framer Motion Starfield w/ Fade In and Twinkling Stars
"use client";
import { useEffect, useState } from "react";
import { motion, useAnimation } from "framer-motion";
interface StarProps {
x: number;
y: number;
size: number;
}
const Star: React.FC<StarProps> = ({ x, y, size }) => {
const controls = useAnimation();
useEffect(() => {
const animateStar = async () => {
while (true) {
await controls.start({ opacity: 1, y: 0 });
await controls.start({ opacity: 0.8, scale: 1.2 });
await controls.start({ opacity: 1, scale: 1 });
await controls.start({ opacity: 1, y: 0 });
// Adjust duration and delay for desired twinkling speed and randomness
await new Promise((resolve) =>
setTimeout(resolve, Math.random() * 2000 + 500)
);
}
};
animateStar();
}, [controls]);
return (
<motion.div
animate={controls}
initial={{ opacity: 0, y: -50 }}
style={{
position: "absolute",
left: x,
top: y,
width: size,
height: size,
borderRadius: "50%",
backgroundColor: "white",
}}
/>
);
};
const Starfield: React.FC = () => {
const [windowSize, setWindowSize] = useState({ width: 0, height: 0 });
useEffect(() => {
const updateWindowSize = () => {
setWindowSize({ width: window.innerWidth, height: window.innerHeight });
};
// Update window size on mount and on window resize
updateWindowSize();
window.addEventListener("resize", updateWindowSize);
return () => {
// Clean up event listener on unmount
window.removeEventListener("resize", updateWindowSize);
};
}, []);
const numberOfStars = 500; // Increase the number of stars
const stars = [];
for (let i = 0; i < numberOfStars; i++) {
const size = Math.random() * 3;
const x = Math.random() * windowSize.width;
const y = Math.random() * windowSize.height;
stars.push(<Star key={i} x={x} y={y} size={size} />);
}
return (
<div style={{ position: "relative", width: "100vw", height: "100vh" }}>
{stars}
</div>
);
};
export default Starfield;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment