"use client"; import { animate } from "motion"; import { useEffect, useRef } from "react"; import initCanvas from "@/utils/init-canvas"; export default function EndpointsExtract({ size = 20 }: { size?: number }) { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = initCanvas(canvas); let isRunning = false; let isActive = false; let diff = 0; const defaultRowAlphas = [ 0.4, 0.04, 0.2, 0.4, 0.2, 0, 0, 0.04, 0.04, 0, 0, 0.2, 0.4, 0.2, 0.04, 0.4, ]; const differs = Array.from({ length: 16 }, () => 0.2 + Math.random() * 0.2); const scaler = size / 20; const render = () => { ctx.fillStyle = "#FF4C00"; ctx.clearRect(0, 0, canvas.width, canvas.height); for (let i = 0; i < 16; i++) { if ([5, 6, 9, 10].includes(i)) continue; ctx.globalAlpha = defaultRowAlphas[i] + diff * differs[i]; ctx.globalAlpha = Math.min(ctx.globalAlpha, 0.4) - Math.max(ctx.globalAlpha - 0.4, 0); ctx.fillRect( (3 + (i % 4) * 4) * scaler, (3 + Math.floor(i / 4) * 4) * scaler, 2 * scaler, 2 * scaler, ); } ctx.globalAlpha = 1; ctx.fillRect(7, 7, 6, 2); ctx.globalAlpha = 0.4; ctx.fillRect(7, 11, 2 + diff * 4, 2); if (isRunning) { requestAnimationFrame(render); } }; const timeouts: number[] = []; let runCount = 0; const duration = 300; const cycle = () => { isRunning = true; animate(diff, 1, { duration: duration / 1000, onUpdate: (value) => { diff = value < 0.5 ? value * 2 : 1 - (value - 0.5) * 2; }, }); timeouts.forEach((timeout) => { window.clearTimeout(timeout); }); timeouts.push( window.setTimeout( () => { isRunning = false; }, Math.max(duration, 300), ), ); runCount += 1; if (runCount === 3 || !isActive) return; timeouts.push( window.setTimeout(() => { cycle(); }, duration), ); }; const activate = () => { if (isActive) return; isActive = true; runCount = 0; cycle(); render(); }; const deactivate = () => { if (!isActive) return; isActive = false; }; render(); canvas.addEventListener("resize", render); const group = canvasRef.current!.closest(".group"); if (group) { group.addEventListener("mouseenter", activate); group.addEventListener("mouseleave", deactivate); return () => { group.removeEventListener("mouseenter", activate); group.removeEventListener("mouseleave", deactivate); }; } }, [size]); return ; }