import { useEffect, useState } from "react"; import { motion, useAnimation } from "framer-motion"; import "./CircularText.css"; const getRotationTransition = (duration, from, loop = true) => ({ from: from, to: from + 360, ease: "linear", duration: duration, type: "tween", repeat: loop ? Infinity : 0, }); const getTransition = (duration, from) => ({ rotate: getRotationTransition(duration, from), scale: { type: "spring", damping: 20, stiffness: 300, }, }); const CircularText = ({ text, spinDuration = 20, onHover = "speedUp", className = "", }) => { const letters = Array.from(text); const controls = useAnimation(); const [currentRotation, setCurrentRotation] = useState(0); useEffect(() => { controls.start({ rotate: currentRotation + 360, scale: 1, transition: getTransition(spinDuration, currentRotation), }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [spinDuration, controls, onHover, text]); const handleHoverStart = () => { if (!onHover) return; switch (onHover) { case "slowDown": controls.start({ rotate: currentRotation + 360, scale: 1, transition: getTransition(spinDuration * 2, currentRotation), }); break; case "speedUp": controls.start({ rotate: currentRotation + 360, scale: 1, transition: getTransition(spinDuration / 4, currentRotation), }); break; case "pause": controls.start({ rotate: currentRotation, scale: 1, transition: { rotate: { type: "spring", damping: 20, stiffness: 300 }, scale: { type: "spring", damping: 20, stiffness: 300 }, }, }); break; case "goBonkers": controls.start({ rotate: currentRotation + 360, scale: 0.8, transition: getTransition(spinDuration / 20, currentRotation), }); break; default: break; } }; const handleHoverEnd = () => { controls.start({ rotate: currentRotation + 360, scale: 1, transition: getTransition(spinDuration, currentRotation), }); }; return ( setCurrentRotation(Number(latest.rotate))} onMouseEnter={handleHoverStart} onMouseLeave={handleHoverEnd} > {letters.map((letter, i) => { const rotation = (360 / letters.length) * i; const factor = Number((Math.PI / letters.length).toFixed(0)); const x = factor * i; const y = factor * i; const transform = `rotateZ(${rotation}deg) translate3d(${x}px, ${y}px, 0)`; return ( {letter} ); })} ); }; export default CircularText;