Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vortex added on main page #183

Merged
merged 2 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions @/components/ui/aurora-background.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"use client";
import { cn } from "../../lib/utils";
import React from "react";

export const AuroraBackground = ({
className,
children,
showRadialGradient = true,
...props
}) => {
return (
<main>
<div
className={cn(
"relative flex flex-col h-[100vh] items-center justify-center bg-zinc-50 dark:bg-zinc-900 text-slate-950 transition-bg",
className,
)}
{...props}
>
<div className="absolute inset-0 overflow-hidden">
<div
// I'm sorry but this is what peak developer performance looks like // trigger warning
className={cn(
`
[--white-gradient:repeating-linear-gradient(100deg,var(--white)_0%,var(--white)_7%,var(--transparent)_10%,var(--transparent)_12%,var(--white)_16%)]
[--dark-gradient:repeating-linear-gradient(100deg,var(--black)_0%,var(--black)_7%,var(--transparent)_10%,var(--transparent)_12%,var(--black)_16%)]
[--aurora:repeating-linear-gradient(100deg,var(--blue-500)_10%,var(--indigo-300)_15%,var(--blue-300)_20%,var(--violet-200)_25%,var(--blue-400)_30%)]
[background-image:var(--white-gradient),var(--aurora)]
dark:[background-image:var(--dark-gradient),var(--aurora)]
[background-size:300%,_200%]
[background-position:50%_50%,50%_50%]
filter blur-[10px] invert dark:invert-0
after:content-[""] after:absolute after:inset-0 after:[background-image:var(--white-gradient),var(--aurora)]
after:dark:[background-image:var(--dark-gradient),var(--aurora)]
after:[background-size:200%,_100%]
after:animate-aurora after:[background-attachment:fixed] after:mix-blend-difference
pointer-events-none
absolute -inset-[10px] opacity-50 will-change-transform`,
showRadialGradient &&
`[mask-image:radial-gradient(ellipse_at_100%_0%,black_10%,var(--transparent)_70%)]`,
)}
></div>
</div>
{children}
</div>
</main>
);
};
234 changes: 234 additions & 0 deletions @/components/ui/vortex.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
"use client";
import { cn } from "../../lib/utils";
import { createNoise3D } from "simplex-noise";
import { motion } from "framer-motion";
import { useRef, useEffect } from "react";

export const Vortex = (props) => {
const canvasRef = useRef(null);
const containerRef = useRef(null);
const particleCount = props.particleCount || 700;
const particlePropCount = 9;
const particlePropsLength = particleCount * particlePropCount;
const rangeY = props.rangeY || 100;
const baseTTL = 50;
const rangeTTL = 150;
const baseSpeed = props.baseSpeed || 0.0;
const rangeSpeed = props.rangeSpeed || 1.5;
const baseRadius = props.baseRadius || 1;
const rangeRadius = props.rangeRadius || 2;
const baseHue = props.baseHue || 220;
const rangeHue = 100;
const noiseSteps = 3;
const xOff = 0.00125;
const yOff = 0.00125;
const zOff = 0.0005;
const backgroundColor = props.backgroundColor || "#000000";
let tick = 0;
const noise3D = createNoise3D();
let particleProps = new Float32Array(particlePropsLength);
let center = [0, 0];

const HALF_PI = 0.5 * Math.PI;
const TAU = 2 * Math.PI;
const TO_RAD = Math.PI / 180;
const rand = (n) => n * Math.random();
const randRange = (n) => n - rand(2 * n);
const fadeInOut = (t, m) => {
let hm = 0.5 * m;
return Math.abs(((t + hm) % m) - hm) / hm;
};
const lerp = (n1, n2, speed) => (1 - speed) * n1 + speed * n2;

const setup = () => {
const canvas = canvasRef.current;
const container = containerRef.current;
if (canvas && container) {
const ctx = canvas.getContext("2d");

if (ctx) {
resize(canvas, ctx);
initParticles();
draw(canvas, ctx);
}
}
};
Comment on lines +43 to +55
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Error handling for 2D context retrieval.
Ensure a fallback if canvas.getContext("2d") is null. Currently, you have a check, but clarifying error logs might help debugging in certain browsers or restricted contexts.


const initParticles = () => {
tick = 0;
// simplex = new SimplexNoise();
particleProps = new Float32Array(particlePropsLength);

for (let i = 0; i < particlePropsLength; i += particlePropCount) {
initParticle(i);
}
};

const initParticle = (i) => {
const canvas = canvasRef.current;
if (!canvas) return;

let x, y, vx, vy, life, ttl, speed, radius, hue;

x = rand(canvas.width);
y = center[1] + randRange(rangeY);
vx = 0;
vy = 0;
life = 0;
ttl = baseTTL + rand(rangeTTL);
speed = baseSpeed + rand(rangeSpeed);
radius = baseRadius + rand(rangeRadius);
hue = baseHue + rand(rangeHue);

particleProps.set([x, y, vx, vy, life, ttl, speed, radius, hue], i);
};

const draw = (canvas, ctx) => {
tick++;

ctx.clearRect(0, 0, canvas.width, canvas.height);

ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);

drawParticles(ctx);
renderGlow(canvas, ctx);
renderToScreen(canvas, ctx);

window.requestAnimationFrame(() => draw(canvas, ctx));
};

const drawParticles = (ctx) => {
for (let i = 0; i < particlePropsLength; i += particlePropCount) {
updateParticle(i, ctx);
}
};

const updateParticle = (i, ctx) => {
const canvas = canvasRef.current;
if (!canvas) return;

let i2 = 1 + i,
i3 = 2 + i,
i4 = 3 + i,
i5 = 4 + i,
i6 = 5 + i,
i7 = 6 + i,
i8 = 7 + i,
i9 = 8 + i;
let n, x, y, vx, vy, life, ttl, speed, x2, y2, radius, hue;

x = particleProps[i];
y = particleProps[i2];
n = noise3D(x * xOff, y * yOff, tick * zOff) * noiseSteps * TAU;
vx = lerp(particleProps[i3], Math.cos(n), 0.5);
vy = lerp(particleProps[i4], Math.sin(n), 0.5);
life = particleProps[i5];
ttl = particleProps[i6];
speed = particleProps[i7];
x2 = x + vx * speed;
y2 = y + vy * speed;
radius = particleProps[i8];
hue = particleProps[i9];

drawParticle(x, y, x2, y2, life, ttl, radius, hue, ctx);

life++;

particleProps[i] = x2;
particleProps[i2] = y2;
particleProps[i3] = vx;
particleProps[i4] = vy;
particleProps[i5] = life;

(checkBounds(x, y, canvas) || life > ttl) && initParticle(i);
};
Comment on lines +107 to +145
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider storing canvas dimension in state & adding a safe unmount.
You handle resize, but a large loop runs on each frame. Double-check for potential memory leaks or unmounted component references.


const drawParticle = (x, y, x2, y2, life, ttl, radius, hue, ctx) => {
ctx.save();
ctx.lineCap = "round";
ctx.lineWidth = radius;
ctx.strokeStyle = `hsla(${hue},100%,60%,${fadeInOut(life, ttl)})`;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x2, y2);
ctx.stroke();
ctx.closePath();
ctx.restore();
};

const checkBounds = (x, y, canvas) => {
return x > canvas.width || x < 0 || y > canvas.height || y < 0;
};

const resize = (canvas, ctx) => {
const container = containerRef.current;
if (!container) return;

// Getting container dimensions
const { clientWidth, clientHeight } = container;

// Setting canvas dimensions to match container
canvas.width = clientWidth;
canvas.height = clientHeight;

center[0] = 0.5 * canvas.width;
center[1] = 0.5 * canvas.height;
};

const renderGlow = (canvas, ctx) => {
ctx.save();
ctx.filter = "blur(8px) brightness(200%)";
ctx.globalCompositeOperation = "lighter";
ctx.drawImage(canvas, 0, 0);
ctx.restore();

ctx.save();
ctx.filter = "blur(4px) brightness(200%)";
ctx.globalCompositeOperation = "lighter";
ctx.drawImage(canvas, 0, 0);
ctx.restore();
};

const renderToScreen = (canvas, ctx) => {
ctx.save();
ctx.globalCompositeOperation = "lighter";
ctx.drawImage(canvas, 0, 0);
ctx.restore();
};

useEffect(() => {
setup();

const handleResize = () => {
const canvas = canvasRef.current;
const ctx = canvas?.getContext("2d");
if (canvas && ctx) {
resize(canvas, ctx);
}
};

window.addEventListener("resize", handleResize);

// Cleanup event listener on component unmount
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);

return (
<div className={cn("relative h-full w-full", props.containerClassName)}>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
ref={containerRef}
className="absolute h-full w-full inset-0 z-0 bg-transparent flex items-center justify-center"
>
<canvas ref={canvasRef}></canvas>
</motion.div>
<div className={cn("relative z-10", props.className)}>
{props.children}
</div>
</div>
);
};
2 changes: 1 addition & 1 deletion app/(auth)/layout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function AuthLayout({ children }) {
className="h-[97%] w-[98%] -z-10 object-cover object-left-bottom opacity-95 rounded-2xl inset-1/2 transform -translate-x-1/2 -translate-y-1/2 absolute"
/>
<h2 className="text-7xl m-5 font-bold pointer-events-none whitespace-pre-wrap bg-gradient-to-b from-white/90 via-white/70 to-zinc-800 bg-clip-text leading-none text-transparent max-sm:text-3xl max-sm:text-center p-2 text-center">
Sanity Gaming
Sanity
</h2>
</div>
<div className="w-1/2 max-md:w-full relative p-2 flex items-center justify-center">
Expand Down
75 changes: 3 additions & 72 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,82 +4,13 @@
html {
scroll-behavior: smooth;
}
.container {
overflow: hidden;
}

.no-scrollbar::-webkit-scrollbar {
display: none;
}
/* @layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;

--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;

--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;

--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;

--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;

--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;

--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;

--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;

--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;

--radius: 0.5rem;
}

.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;

--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;

--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;

--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;

--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;

--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;

--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;

--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;

--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
} */
* {
padding: 0;
margin: 0;
Expand Down
Loading
Loading