aboutsummaryrefslogtreecommitdiff
path: root/src/components/ui/wavy-background.tsx
diff options
context:
space:
mode:
authorsotech117 <michael_foiani@brown.edu>2025-09-23 01:46:55 -0400
committersotech117 <michael_foiani@brown.edu>2025-09-23 01:46:55 -0400
commit3a712982307391ae1196f50e252cb37ed5f67ccb (patch)
tree279aa2d97198a08aef2eb1c80bc5008763eb98da /src/components/ui/wavy-background.tsx
parentc5547dc1ba827a4256fbe1ed08bda61f8c660815 (diff)
add hero and get-started page
Diffstat (limited to 'src/components/ui/wavy-background.tsx')
-rw-r--r--src/components/ui/wavy-background.tsx132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/components/ui/wavy-background.tsx b/src/components/ui/wavy-background.tsx
new file mode 100644
index 0000000..4fbc374
--- /dev/null
+++ b/src/components/ui/wavy-background.tsx
@@ -0,0 +1,132 @@
+"use client";
+import { cn } from "@/lib/utils";
+import React, { useEffect, useRef, useState } from "react";
+import { createNoise3D } from "simplex-noise";
+
+export const WavyBackground = ({
+ children,
+ className,
+ containerClassName,
+ colors,
+ waveWidth,
+ backgroundFill,
+ blur = 10,
+ speed = "fast",
+ waveOpacity = 0.5,
+ ...props
+}: {
+ children?: any;
+ className?: string;
+ containerClassName?: string;
+ colors?: string[];
+ waveWidth?: number;
+ backgroundFill?: string;
+ blur?: number;
+ speed?: "slow" | "fast";
+ waveOpacity?: number;
+ [key: string]: any;
+}) => {
+ const noise = createNoise3D();
+ let w: number,
+ h: number,
+ nt: number,
+ i: number,
+ x: number,
+ ctx: any,
+ canvas: any;
+ const canvasRef = useRef<HTMLCanvasElement>(null);
+ const getSpeed = () => {
+ switch (speed) {
+ case "slow":
+ return 0.001;
+ case "fast":
+ return 0.002;
+ default:
+ return 0.001;
+ }
+ };
+
+ const init = () => {
+ canvas = canvasRef.current;
+ ctx = canvas.getContext("2d");
+ w = ctx.canvas.width = window.innerWidth;
+ h = ctx.canvas.height = window.innerHeight;
+ ctx.filter = `blur(${blur}px)`;
+ nt = 0;
+ window.onresize = function () {
+ w = ctx.canvas.width = window.innerWidth;
+ h = ctx.canvas.height = window.innerHeight;
+ ctx.filter = `blur(${blur}px)`;
+ };
+ render();
+ };
+
+ const waveColors = colors ?? [
+ "#38bdf8",
+ "#818cf8",
+ "#c084fc",
+ "#e879f9",
+ "#22d3ee",
+ ];
+ const drawWave = (n: number) => {
+ nt += getSpeed();
+ for (i = 0; i < n; i++) {
+ ctx.beginPath();
+ ctx.lineWidth = waveWidth || 50;
+ ctx.strokeStyle = waveColors[i % waveColors.length];
+ for (x = 0; x < w; x += 5) {
+ var y = noise(x / 800, 0.3 * i, nt) * 100;
+ ctx.lineTo(x, y + h * 0.5); // adjust for height, currently at 50% of the container
+ }
+ ctx.stroke();
+ ctx.closePath();
+ }
+ };
+
+ let animationId: number;
+ const render = () => {
+ ctx.fillStyle = backgroundFill || "black";
+ ctx.globalAlpha = waveOpacity || 0.5;
+ ctx.fillRect(0, 0, w, h);
+ drawWave(5);
+ animationId = requestAnimationFrame(render);
+ };
+
+ useEffect(() => {
+ init();
+ return () => {
+ cancelAnimationFrame(animationId);
+ };
+ }, []);
+
+ const [isSafari, setIsSafari] = useState(false);
+ useEffect(() => {
+ // I'm sorry but i have got to support it on safari.
+ setIsSafari(
+ typeof window !== "undefined" &&
+ navigator.userAgent.includes("Safari") &&
+ !navigator.userAgent.includes("Chrome")
+ );
+ }, []);
+
+ return (
+ <div
+ className={cn(
+ "h-screen flex flex-col items-center justify-center",
+ containerClassName
+ )}
+ >
+ <canvas
+ className="absolute inset-0 z-0"
+ ref={canvasRef}
+ id="canvas"
+ style={{
+ ...(isSafari ? { filter: `blur(${blur}px)` } : {}),
+ }}
+ ></canvas>
+ <div className={cn("relative z-10", className)} {...props}>
+ {children}
+ </div>
+ </div>
+ );
+};