From 716c9f1b0c523633f8168affba02d67219169822 Mon Sep 17 00:00:00 2001 From: Jonghyeon Ko Date: Mon, 18 Mar 2024 05:20:53 +0900 Subject: [PATCH] =?UTF-8?q?feat(people):=20StarBackground=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/app/components/StarBackground.tsx | 164 ++++++++++++++++++ apps/people/src/app/page.tsx | 15 +- 2 files changed, 172 insertions(+), 7 deletions(-) create mode 100644 apps/people/src/app/components/StarBackground.tsx diff --git a/apps/people/src/app/components/StarBackground.tsx b/apps/people/src/app/components/StarBackground.tsx new file mode 100644 index 0000000..cdcfcee --- /dev/null +++ b/apps/people/src/app/components/StarBackground.tsx @@ -0,0 +1,164 @@ +'use client' + +import React, { useEffect } from 'react' + +interface Props { + speedFactor?: number + backgroundColor?: string + starColor?: [number, number, number] + starCount?: number +} + +export default function StarBackground(props: Props) { + const { + speedFactor = 0.05, + backgroundColor = 'black', + starColor = [255, 255, 255], + starCount = 5000, + } = props + + useEffect(() => { + const canvas = document.getElementById( + 'starfield' + ) as HTMLCanvasElement | null + + if (canvas) { + const c = canvas.getContext('2d') + + if (c) { + let w = window.innerWidth + let h = window.innerHeight + + const setCanvasExtents = () => { + canvas.width = w + canvas.height = h + } + + setCanvasExtents() + + window.onresize = () => { + setCanvasExtents() + } + + const makeStars = (count: number) => { + const out = [] + for (let i = 0; i < count; i++) { + const s = { + x: Math.random() * 1600 - 800, + y: Math.random() * 900 - 450, + z: Math.random() * 1000, + } + out.push(s) + } + return out + } + + const stars = makeStars(starCount) + + const clear = () => { + c.fillStyle = backgroundColor + c.fillRect(0, 0, canvas.width, canvas.height) + } + + const putPixel = (x: number, y: number, brightness: number) => { + const rgb = + 'rgba(' + + starColor[0] + + ',' + + starColor[1] + + ',' + + starColor[2] + + ',' + + brightness + + ')' + c.fillStyle = rgb + c.fillRect(x, y, 1, 1) + } + + const moveStars = (distance: number) => { + const count = stars.length + for (let i = 0; i < count; i++) { + const s = stars[i] + s.z -= distance + while (s.z <= 1) { + s.z += 1000 + } + } + } + + let prevTime: number + const init = (time: number) => { + prevTime = time + requestAnimationFrame(tick) + } + + const tick = (time: number) => { + const elapsed = time - prevTime + prevTime = time + + moveStars(elapsed * speedFactor) + + clear() + + const cx = w / 2 + const cy = h / 2 + + const count = stars.length + for (let i = 0; i < count; i++) { + const star = stars[i] + + const x = cx + star.x / (star.z * 0.001) + const y = cy + star.y / (star.z * 0.001) + + if (x < 0 || x >= w || y < 0 || y >= h) { + continue + } + + const d = star.z / 1000.0 + const b = 1 - d * d + + putPixel(x, y, b) + } + + requestAnimationFrame(tick) + } + + requestAnimationFrame(init) + + // add window resize listener: + window.addEventListener('resize', function () { + w = window.innerWidth + h = window.innerHeight + setCanvasExtents() + }) + } else { + console.error('Could not get 2d context from canvas element') + } + } else { + console.error('Could not find canvas element with id "starfield"') + } + + return () => { + window.onresize = null + } + }, [starColor, backgroundColor, speedFactor, starCount]) + + return ( + + ) +} diff --git a/apps/people/src/app/page.tsx b/apps/people/src/app/page.tsx index 032bb6d..1953706 100644 --- a/apps/people/src/app/page.tsx +++ b/apps/people/src/app/page.tsx @@ -6,6 +6,7 @@ import { SuspenseImage } from '@suspensive/react-image' import { Reorder, motion } from 'framer-motion' import { useState } from 'react' import { Card, type CardData } from './components/Card' +import StarBackground from './components/StarBackground' import { initialCards } from '~/mock/cardDatas' export default function Home() { @@ -15,13 +16,13 @@ export default function Home() { >(null) return ( - + +