feat: Initialize portfolio project with core pages, UI components, and configuration files.
This commit is contained in:
1 parent
aa07d6faeb
commit
0523052864
38 files changed
+1165
-460
No files matched your search
+41
-27
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
import React, { useRef, useEffect, useCallback, useMemo } from 'react';
|
||||
import { gsap } from 'gsap';
|
||||
import { InertiaPlugin } from 'gsap/InertiaPlugin';
|
||||
"use client";
|
||||
import React, { useRef, useEffect, useCallback, useMemo } from "react";
|
||||
import { gsap } from "gsap";
|
||||
import { InertiaPlugin } from "gsap/InertiaPlugin";
|
||||
|
||||
gsap.registerPlugin(InertiaPlugin);
|
||||
|
||||
@@ -46,15 +46,15 @@ function hexToRgb(hex: string) {
|
||||
return {
|
||||
r: parseInt(m[1], 16),
|
||||
g: parseInt(m[2], 16),
|
||||
b: parseInt(m[3], 16)
|
||||
b: parseInt(m[3], 16),
|
||||
};
|
||||
}
|
||||
|
||||
const DotGrid: React.FC<DotGridProps> = ({
|
||||
dotSize = 16,
|
||||
gap = 32,
|
||||
baseColor = '#5227FF',
|
||||
activeColor = '#5227FF',
|
||||
baseColor = "#5227FF",
|
||||
activeColor = "#5227FF",
|
||||
proximity = 150,
|
||||
speedTrigger = 100,
|
||||
shockRadius = 250,
|
||||
@@ -62,8 +62,8 @@ const DotGrid: React.FC<DotGridProps> = ({
|
||||
maxSpeed = 5000,
|
||||
resistance = 750,
|
||||
returnDuration = 1.5,
|
||||
className = '',
|
||||
style
|
||||
className = "",
|
||||
style,
|
||||
}) => {
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
@@ -76,14 +76,14 @@ const DotGrid: React.FC<DotGridProps> = ({
|
||||
speed: 0,
|
||||
lastTime: 0,
|
||||
lastX: 0,
|
||||
lastY: 0
|
||||
lastY: 0,
|
||||
});
|
||||
|
||||
const baseRgb = useMemo(() => hexToRgb(baseColor), [baseColor]);
|
||||
const activeRgb = useMemo(() => hexToRgb(activeColor), [activeColor]);
|
||||
|
||||
const circlePath = useMemo(() => {
|
||||
if (typeof window === 'undefined' || !window.Path2D) return null;
|
||||
if (typeof window === "undefined" || !window.Path2D) return null;
|
||||
|
||||
const p = new Path2D();
|
||||
p.arc(0, 0, dotSize / 2, 0, Math.PI * 2);
|
||||
@@ -102,7 +102,7 @@ const DotGrid: React.FC<DotGridProps> = ({
|
||||
canvas.height = height * dpr;
|
||||
canvas.style.width = `${width}px`;
|
||||
canvas.style.height = `${height}px`;
|
||||
const ctx = canvas.getContext('2d');
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (ctx) ctx.scale(dpr, dpr);
|
||||
|
||||
const cols = Math.floor((width + gap) / (dotSize + gap));
|
||||
@@ -138,7 +138,7 @@ const DotGrid: React.FC<DotGridProps> = ({
|
||||
const draw = () => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext('2d');
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (!ctx) return;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
@@ -178,15 +178,15 @@ const DotGrid: React.FC<DotGridProps> = ({
|
||||
useEffect(() => {
|
||||
buildGrid();
|
||||
let ro: ResizeObserver | null = null;
|
||||
if ('ResizeObserver' in window) {
|
||||
if ("ResizeObserver" in window) {
|
||||
ro = new ResizeObserver(buildGrid);
|
||||
wrapperRef.current && ro.observe(wrapperRef.current);
|
||||
} else {
|
||||
(window as Window).addEventListener('resize', buildGrid);
|
||||
(window as Window).addEventListener("resize", buildGrid);
|
||||
}
|
||||
return () => {
|
||||
if (ro) ro.disconnect();
|
||||
else window.removeEventListener('resize', buildGrid);
|
||||
else window.removeEventListener("resize", buildGrid);
|
||||
};
|
||||
}, [buildGrid]);
|
||||
|
||||
@@ -231,10 +231,10 @@ const DotGrid: React.FC<DotGridProps> = ({
|
||||
xOffset: 0,
|
||||
yOffset: 0,
|
||||
duration: returnDuration,
|
||||
ease: 'elastic.out(1,0.75)'
|
||||
ease: "elastic.out(1,0.75)",
|
||||
});
|
||||
dot._inertiaApplied = false;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -259,29 +259,43 @@ const DotGrid: React.FC<DotGridProps> = ({
|
||||
xOffset: 0,
|
||||
yOffset: 0,
|
||||
duration: returnDuration,
|
||||
ease: 'elastic.out(1,0.75)'
|
||||
ease: "elastic.out(1,0.75)",
|
||||
});
|
||||
dot._inertiaApplied = false;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const throttledMove = throttle(onMove, 50);
|
||||
window.addEventListener('mousemove', throttledMove, { passive: true });
|
||||
window.addEventListener('click', onClick);
|
||||
window.addEventListener("mousemove", throttledMove, { passive: true });
|
||||
window.addEventListener("click", onClick);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('mousemove', throttledMove);
|
||||
window.removeEventListener('click', onClick);
|
||||
window.removeEventListener("mousemove", throttledMove);
|
||||
window.removeEventListener("click", onClick);
|
||||
};
|
||||
}, [maxSpeed, speedTrigger, proximity, resistance, returnDuration, shockRadius, shockStrength]);
|
||||
}, [
|
||||
maxSpeed,
|
||||
speedTrigger,
|
||||
proximity,
|
||||
resistance,
|
||||
returnDuration,
|
||||
shockRadius,
|
||||
shockStrength,
|
||||
]);
|
||||
|
||||
return (
|
||||
<section className={`p-4 flex items-center justify-center h-full w-full relative ${className}`} style={style}>
|
||||
<section
|
||||
className={`p-4 flex items-center justify-center h-full w-full relative ${className}`}
|
||||
style={style}
|
||||
>
|
||||
<div ref={wrapperRef} className="w-full h-full relative">
|
||||
<canvas ref={canvasRef} className="absolute inset-0 w-full h-full pointer-events-none" />
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="absolute inset-0 w-full h-full pointer-events-none"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user