diff options
author | sotech117 <michael_foiani@brown.edu> | 2025-09-23 01:46:55 -0400 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2025-09-23 01:46:55 -0400 |
commit | 3a712982307391ae1196f50e252cb37ed5f67ccb (patch) | |
tree | 279aa2d97198a08aef2eb1c80bc5008763eb98da /src/components/ui/wavy-background.tsx | |
parent | c5547dc1ba827a4256fbe1ed08bda61f8c660815 (diff) |
add hero and get-started page
Diffstat (limited to 'src/components/ui/wavy-background.tsx')
-rw-r--r-- | src/components/ui/wavy-background.tsx | 132 |
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> + ); +}; |