-
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.
Create star background function and implement on pages (#174)
* feat(frontend): ✨ add star background to pages added to most backgrounds except globe and blog (because of potential merge issues) * fix --------- Co-authored-by: Lukas <lukas@thrane.name>
- Loading branch information
2 people
authored and
GitHub
committed
Apr 2, 2024
1 parent
1791fc0
commit 6acec7e
Showing
3 changed files
with
173 additions
and
1 deletion.
There are no files selected for viewing
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
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
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,167 @@ | ||
| "use client"; | ||
|
|
||
| import React, { useEffect } from "react"; | ||
|
|
||
| interface Props { | ||
| speedFactor?: number; | ||
| backgroundColor?: string; | ||
| starColor?: [number, number, number]; | ||
| starCount?: number; | ||
| } | ||
|
|
||
| export default function Starfield(props: Props) { | ||
| const { | ||
| speedFactor = 0.05, | ||
| backgroundColor = "black", | ||
| starColor = [255, 255, 255], | ||
| starCount = 5000, | ||
| } = props; | ||
|
|
||
| useEffect(() => { | ||
| const canvas = document.getElementById( | ||
| "starfield", | ||
| ) as HTMLCanvasElement; | ||
|
|
||
| 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; | ||
| }; | ||
|
|
||
| let 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 (var 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) => { | ||
| let elapsed = time - prevTime; | ||
| prevTime = time; | ||
|
|
||
| moveStars(elapsed * speedFactor); | ||
|
|
||
| clear(); | ||
|
|
||
| const cx = w / 2; | ||
| const cy = h / 2; | ||
|
|
||
| const count = stars.length; | ||
| for (var 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 ( | ||
| <canvas | ||
| id="starfield" | ||
| style={{ | ||
| padding: 0, | ||
| margin: 0, | ||
| position: "fixed", | ||
| top: 0, | ||
| right: 0, | ||
| bottom: 0, | ||
| left: 0, | ||
| zIndex: -1, | ||
| opacity: 1, | ||
| pointerEvents: "none", | ||
| mixBlendMode: "screen", | ||
| }} | ||
| ></canvas> | ||
| ); | ||
| } | ||
|
|
||
| // https://github.com/designly1/react-starfield | ||
| // MIT License |