Animation Added and Gif file updated
This commit is contained in:
123
app/components/canvas/GravityWave.tsx
Normal file
123
app/components/canvas/GravityWave.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useRef } from "react";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const GravityWave: React.FC<Props> = ({ className }) => {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (!ctx) return;
|
||||
|
||||
// Initialize dimensions based on parent container
|
||||
let width = canvas.width = canvas.parentElement?.clientWidth || window.innerWidth;
|
||||
let height = canvas.height = canvas.parentElement?.clientHeight || window.innerHeight;
|
||||
|
||||
let animationFrameId: number;
|
||||
let time = 0;
|
||||
|
||||
// Configuration
|
||||
const gap = 50;
|
||||
const rows = Math.ceil(height / gap) + 4;
|
||||
const cols = Math.ceil(width / gap) + 4;
|
||||
|
||||
// Mouse state
|
||||
const mouse = { x: -500, y: -500 };
|
||||
|
||||
const handleResize = () => {
|
||||
// Resize based on parent element
|
||||
if (canvas.parentElement) {
|
||||
width = canvas.width = canvas.parentElement.clientWidth;
|
||||
height = canvas.height = canvas.parentElement.clientHeight;
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
mouse.x = e.clientX - rect.left;
|
||||
mouse.y = e.clientY - rect.top;
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
// Attach mouse move to the specific canvas/container, not window, if you want localized interaction
|
||||
// But keeping it on window usually feels smoother for "approaching" the section
|
||||
window.addEventListener("mousemove", handleMouseMove);
|
||||
|
||||
const render = () => {
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
time += 0.02;
|
||||
|
||||
ctx.shadowBlur = 4;
|
||||
ctx.shadowColor = "rgba(34, 211, 238, 0.5)";
|
||||
|
||||
const gradient = ctx.createLinearGradient(0, 0, width, height);
|
||||
gradient.addColorStop(0, "rgba(34, 211, 238, 0.4)");
|
||||
gradient.addColorStop(1, "rgba(52, 211, 153, 0.4)");
|
||||
|
||||
ctx.strokeStyle = gradient;
|
||||
ctx.lineWidth = 1.5;
|
||||
|
||||
// Re-calculate rows/cols in case of resize
|
||||
const currentRows = Math.ceil(height / gap) + 4;
|
||||
const currentCols = Math.ceil(width / gap) + 4;
|
||||
|
||||
for (let iy = 0; iy < currentRows; iy++) {
|
||||
const yBase = iy * gap;
|
||||
ctx.beginPath();
|
||||
for (let ix = 0; ix < currentCols; ix++) {
|
||||
const xBase = ix * gap;
|
||||
|
||||
const waveOffset = Math.sin(ix * 0.2 + time) * 8 + Math.cos(iy * 0.3 + time) * 8;
|
||||
const dx = xBase - mouse.x;
|
||||
const dy = yBase - mouse.y;
|
||||
const dist = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
const maxDist = 400;
|
||||
let gravityX = 0;
|
||||
let gravityY = 0;
|
||||
|
||||
if (dist < maxDist) {
|
||||
const force = (maxDist - dist) / maxDist;
|
||||
const power = force * 60;
|
||||
const angle = Math.atan2(dy, dx);
|
||||
gravityX = Math.cos(angle) * power;
|
||||
gravityY = Math.sin(angle) * power;
|
||||
}
|
||||
|
||||
const xFinal = xBase + gravityX;
|
||||
const yFinal = yBase + waveOffset + gravityY;
|
||||
|
||||
if (ix === 0) ctx.moveTo(xFinal, yFinal);
|
||||
else ctx.lineTo(xFinal, yFinal);
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
animationFrameId = requestAnimationFrame(render);
|
||||
};
|
||||
|
||||
render();
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleResize);
|
||||
window.removeEventListener("mousemove", handleMouseMove);
|
||||
cancelAnimationFrame(animationFrameId);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className={`block w-full h-full ${className}`}
|
||||
style={{ touchAction: "none" }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default GravityWave;
|
||||
Reference in New Issue
Block a user