-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathCircularText.jsx
More file actions
109 lines (96 loc) · 2.73 KB
/
Copy pathCircularText.jsx
File metadata and controls
109 lines (96 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { useEffect } from 'react';
import { motion, useAnimation, useMotionValue } from 'motion/react';
import './CircularText.css';
const getRotationTransition = (duration, from, loop = true) => ({
from,
to: from + 360,
ease: 'linear',
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 rotation = useMotionValue(0);
useEffect(() => {
const start = rotation.get();
controls.start({
rotate: start + 360,
scale: 1,
transition: getTransition(spinDuration, start)
});
}, [spinDuration, text, onHover, controls, rotation]);
const handleHoverStart = () => {
const start = rotation.get();
if (!onHover) return;
let transitionConfig;
let scaleVal = 1;
switch (onHover) {
case 'slowDown':
transitionConfig = getTransition(spinDuration * 2, start);
break;
case 'speedUp':
transitionConfig = getTransition(spinDuration / 4, start);
break;
case 'pause':
transitionConfig = {
rotate: { type: 'spring', damping: 20, stiffness: 300 },
scale: { type: 'spring', damping: 20, stiffness: 300 }
};
scaleVal = 1;
break;
case 'goBonkers':
transitionConfig = getTransition(spinDuration / 20, start);
scaleVal = 0.8;
break;
default:
transitionConfig = getTransition(spinDuration, start);
}
controls.start({
rotate: start + 360,
scale: scaleVal,
transition: transitionConfig
});
};
const handleHoverEnd = () => {
const start = rotation.get();
controls.start({
rotate: start + 360,
scale: 1,
transition: getTransition(spinDuration, start)
});
};
return (
<motion.div
className={`circular-text ${className}`}
style={{ rotate: rotation }}
initial={{ rotate: 0 }}
animate={controls}
onMouseEnter={handleHoverStart}
onMouseLeave={handleHoverEnd}
>
{letters.map((letter, i) => {
const rotationDeg = (360 / letters.length) * i;
const factor = Math.PI / letters.length;
const x = factor * i;
const y = factor * i;
const transform = `rotateZ(${rotationDeg}deg) translate3d(${x}px, ${y}px, 0)`;
return (
<span key={i} style={{ transform, WebkitTransform: transform }}>
{letter}
</span>
);
})}
</motion.div>
);
};
export default CircularText;