Skip to content

Commit

Permalink
Create star background function and implement on pages (#174)
Browse files Browse the repository at this point in the history
* 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
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 1 deletion.
6 changes: 5 additions & 1 deletion frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const metadata: Metadata = {
};

import ErrorBoundaryNavigation from "@/components/ErrorBoundaryNavigation";
import Starfield from "@/components/starBackground/Starfield";

export default function RootLayout({
children,
Expand All @@ -27,7 +28,10 @@ export default function RootLayout({
<ApolloWrapper>
<Navbar />
<ErrorBoundaryNavigation>
<main className="flex-grow">{children}</main>
<main className="flex-grow">
<Starfield />
{children}
</main>
</ErrorBoundaryNavigation>
<Footer />
</ApolloWrapper>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/app/satellites/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Link from "next/link";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import SatelliteStatsTable from "@/components/ui/satelliteStatsTable";
import Image from "next/image";

const HOST_URL = process.env.HOST_URL;
const GET_SATELLITES = gql(`
query GET_SATELLITES {
Expand Down
167 changes: 167 additions & 0 deletions frontend/src/components/starBackground/Starfield.tsx
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

0 comments on commit 6acec7e

Please sign in to comment.