"use client" import { useEffect, useState, useRef } from "react" import { useMaterial } from "@/contexts/material-context" import { useColorPalette } from "@/contexts/color-context" export function GlassShaderEffect() { const { selectedMaterial } = useMaterial() const { primaryColor } = useColorPalette() const [isGlass, setIsGlass] = useState(false) const canvasRef = useRef(null) const bannerRef = useRef(null) const animationRef = useRef(0) const [dimensions, setDimensions] = useState({ width: 0, height: 0 }) const [position, setPosition] = useState({ top: 0, left: 0 }) // Parse the primary color to RGB const getRGBFromHex = (hex: string) => { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) return result ? { r: Number.parseInt(result[1], 16), g: Number.parseInt(result[2], 16), b: Number.parseInt(result[3], 16), } : { r: 59, g: 130, b: 246 } // Default blue if parsing fails } // Find and track the banner element useEffect(() => { // Define updateDimensions function first const updateDimensions = () => { if (bannerRef.current) { const rect = bannerRef.current.getBoundingClientRect() setDimensions({ width: rect.width, height: rect.height, }) setPosition({ top: rect.top + window.scrollY, left: rect.left + window.scrollX, }) } } // Define findBanner function that uses updateDimensions const findBanner = () => { const banner = document.querySelector("#banner-version-two") as HTMLElement if (banner) { bannerRef.current = banner updateDimensions() } else { // If banner not found, try again in a moment setTimeout(findBanner, 100) } } // Start the process findBanner() // Add event listeners window.addEventListener("resize", updateDimensions) window.addEventListener("scroll", updateDimensions) // Update dimensions periodically to handle dynamic content const interval = setInterval(updateDimensions, 1000) return () => { window.removeEventListener("resize", updateDimensions) window.removeEventListener("scroll", updateDimensions) clearInterval(interval) } }, []) // Update isGlass state when material changes useEffect(() => { setIsGlass(selectedMaterial?.id === "glass") }, [selectedMaterial]) // Draw the animated gradient useEffect(() => { if (!canvasRef.current || !isGlass || dimensions.width === 0) return const canvas = canvasRef.current const ctx = canvas.getContext("2d") if (!ctx) return // Set canvas dimensions canvas.width = dimensions.width canvas.height = dimensions.height // Parse primary color const rgb = getRGBFromHex(primaryColor) // Animation variables let time = 0 const speed = 0.001 // Slow animation speed for subtlety // Animation function const animate = () => { time += speed // Create gradient const gradient = ctx.createRadialGradient( canvas.width / 2 + Math.sin(time) * canvas.width * 0.3, canvas.height / 2 + Math.cos(time * 0.7) * canvas.height * 0.3, 0, canvas.width / 2, canvas.height / 2, Math.max(canvas.width, canvas.height) * 0.8, ) // Use primary color with varying opacity gradient.addColorStop(0, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.1)`) gradient.addColorStop(0.5, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.05)`) gradient.addColorStop(1, `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.02)`) // Clear and fill ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.fillStyle = gradient ctx.fillRect(0, 0, canvas.width, canvas.height) // Continue animation if still glass material if (isGlass) { animationRef.current = requestAnimationFrame(animate) } } // Start animation animate() // Cleanup return () => { cancelAnimationFrame(animationRef.current) } }, [isGlass, primaryColor, dimensions]) // Don't render anything if not glass material if (!isGlass) return null return (