#app
View Compiled
*
box-sizing border-box
body
display grid
place-items center
min-height 100vh
overflow hidden
canvas
position fixed
inset 0
background hsl(0, 0%, 15%)
z-index -1
height 100vh
width 100vw
View Compiled
import React from 'https://cdn.skypack.dev/react'
import ReactDOM from 'https://cdn.skypack.dev/react-dom'
import gsap from 'https://cdn.skypack.dev/gsap'
import { GUI } from 'https://cdn.skypack.dev/dat.gui'
const ROOT_NODE = document.querySelector('#app')
const Starscape = ({ densityRatio = 0.5, sizeLimit = 5, defaultAlpha = 0.5 }) => {
const canvasRef = React.useRef(null)
const contextRef = React.useRef(null)
const starsRef = React.useRef(null)
React.useEffect(() => {
contextRef.current = canvasRef.current.getContext('2d')
const LOAD = () => {
const VMIN = Math.min(window.innerHeight, window.innerWidth)
const STAR_COUNT = Math.floor(VMIN * densityRatio)
canvasRef.current.width = window.innerWidth
canvasRef.current.height = window.innerHeight
starsRef.current = new Array(STAR_COUNT).fill().map(() => ({
x: gsap.utils.random(0, window.innerWidth, 1),
y: gsap.utils.random(0, window.innerHeight, 1),
size: gsap.utils.random(1, sizeLimit, 1),
scale: 1,
alpha: gsap.utils.random(0.1, defaultAlpha, 0.1),
}))
}
const RENDER = () => {
contextRef.current.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height)
starsRef.current.forEach(star => {
contextRef.current.fillStyle = `hsla(0, 100%, 100%, ${star.alpha})`
contextRef.current.beginPath()
contextRef.current.arc(star.x, star.y, star.size / 2, 0, Math.PI * 2)
contextRef.current.fill()
})
}
LOAD()
RENDER()
}, [densityRatio, sizeLimit])
return <canvas ref={canvasRef} />
}
const App = () => {
const [density, setDensity] = React.useState(0.5)
const [size, setSize] = React.useState(5)
React.useEffect(() => {
const CONFIG = {
density: 0.5,
size: 5
}
const CTRL = new GUI()
CTRL.add(CONFIG, 'density', 0.1, 2, 0.1).name('Density').onChange(setDensity)
CTRL.add(CONFIG, 'size', 1, 30, 1).name('Size').onChange(setSize)
}, [])
return <Starscape densityRatio={density} sizeLimit={size} />
}
ReactDOM.render(<App/>, ROOT_NODE)
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.