Files
sass-mohfarawati/components/layout/animated-logo.tsx
T
2026-03-07 20:08:59 +01:00

84 lines
2.3 KiB
TypeScript

"use client";
import { motion, useMotionTemplate, useMotionValue, useSpring } from "framer-motion";
import Image from "next/image";
export function AnimatedLogo() {
const rotateX = useMotionValue(0);
const rotateY = useMotionValue(0);
const springX = useSpring(rotateX, { stiffness: 180, damping: 18 });
const springY = useSpring(rotateY, { stiffness: 180, damping: 18 });
const glowX = useMotionTemplate`${springY}px`;
const glowY = useMotionTemplate`${springX}px`;
function handlePointerMove(event: React.PointerEvent<HTMLDivElement>) {
const rect = event.currentTarget.getBoundingClientRect();
const offsetX = event.clientX - rect.left - rect.width / 2;
const offsetY = event.clientY - rect.top - rect.height / 2;
rotateX.set((-offsetY / rect.height) * 14);
rotateY.set((offsetX / rect.width) * 14);
}
function handlePointerLeave() {
rotateX.set(0);
rotateY.set(0);
}
return (
<motion.div
onPointerMove={handlePointerMove}
onPointerLeave={handlePointerLeave}
animate={{
y: [0, -6, 0],
scale: [1, 1.015, 1],
}}
transition={{
duration: 8,
repeat: Number.POSITIVE_INFINITY,
ease: "easeInOut",
}}
style={{
rotateX: springX,
rotateY: springY,
transformPerspective: 900,
}}
className="relative mx-auto flex w-fit items-center justify-center"
>
<motion.div
animate={{
opacity: [0.28, 0.42, 0.28],
scale: [0.96, 1.04, 0.96],
}}
transition={{
duration: 6,
repeat: Number.POSITIVE_INFINITY,
ease: "easeInOut",
}}
style={{
x: glowX,
y: glowY,
}}
className="absolute inset-0 -z-10 rounded-full bg-brand-primary/20 blur-3xl"
/>
<Image
src="/logos/light-primary.svg"
alt="mohfarawati"
width={220}
height={52}
className="block h-auto w-[140px] dark:hidden sm:w-[180px] lg:w-[220px]"
priority
/>
<Image
src="/logos/dark-primary.svg"
alt="mohfarawati"
width={220}
height={52}
className="hidden h-auto w-[140px] dark:block sm:w-[180px] lg:w-[220px]"
priority
/>
</motion.div>
);
}