-
Notifications
You must be signed in to change notification settings - Fork 2
/
ShuffleTextInOut.tsx
113 lines (103 loc) · 3.26 KB
/
ShuffleTextInOut.tsx
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
110
111
112
113
import { ShuffleText } from '@/types/animations';
import gsap from 'gsap';
import SplitText from 'gsap/dist/SplitText';
import ScrambleTextPlugin from 'gsap/dist/ScrambleTextPlugin';
import { useRef } from 'react';
import useIsomorphicLayoutEffect from '@/hooks/useIsomorphicLayoutEffect';
import useTransitionContext from '@/context/transitionContext';
import { shuffle } from '@/utils/array';
if (typeof window !== 'undefined') {
gsap.registerPlugin(SplitText);
}
gsap.registerPlugin(ScrambleTextPlugin);
export default function ShuffleTextInOut({
children,
fade = true,
durationIn = 0.8,
durationOut = 0.5,
delay = 0,
delayOut = 0,
revealDelayIn = 0.5,
revealDelayOut = 0.35,
ease = 'none',
easeOut = 'none',
target,
skipOutro,
watch = false,
start = 'top bottom',
end = 'bottom top',
scrub = false,
markers
}: ShuffleText) {
const { timeline } = useTransitionContext();
const element = useRef<HTMLDivElement | null>(null);
useIsomorphicLayoutEffect(() => {
const scrollTrigger = watch ? {
scrollTrigger: {
trigger: element.current,
start,
end,
scrub,
markers: markers
}
} : {};
const ctx = gsap.context(() => {
/* Sets opacity on the parent */
if (fade) {
gsap.to(element.current, {
opacity: 1,
delay,
...scrollTrigger
});
}
/* Splits the target */
const splitWord = new SplitText(target, {
type: 'words'
});
const words = splitWord.words;
/* Intro animation */
words.forEach(word => {
const splitText = new SplitText(word);
const chars = shuffle(splitText.chars as HTMLElement[]);
let string = '';
chars.forEach(char => {
string += char.innerText;
});
gsap.to(word, {
ease,
delay,
duration: durationIn,
scrambleText:{
text: '{original}',
chars: string,
revealDelay: revealDelayIn
},
...scrollTrigger
});
/* Outro animation */
if (!skipOutro) {
timeline?.add(
gsap.to(word, {
opacity: fade ? 0 : 1,
ease: easeOut,
delay: delayOut,
duration: durationOut,
scrambleText:{
text: '{original}',
chars: string,
revealDelay: revealDelayOut
}
}),
0
);
}
});
}, element);
return () => ctx.revert();
}, []);
return (
<div ref={element} style={{ opacity: fade ? 0 : 1 }}>
{children}
</div>
);
};