File tree Expand file tree Collapse file tree 1 file changed +62
-0
lines changed
Expand file tree Collapse file tree 1 file changed +62
-0
lines changed Original file line number Diff line number Diff line change 1+ "use client" ;
2+
3+ import { useEffect , useState } from "react" ;
4+
5+ import { motion } from "framer-motion" ;
6+
7+ interface TextScrambleProps {
8+ children : string ;
9+ speed ?: number ;
10+ characterSet ?: string ;
11+ className ?: string ;
12+ }
13+
14+ const DEFAULT_CHARS =
15+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ;
16+
17+ function getRandomChar ( charSet : string ) {
18+ return charSet [ Math . floor ( Math . random ( ) * charSet . length ) ] ;
19+ }
20+
21+ export const TextScramble = ( {
22+ children,
23+ speed = 50 ,
24+ characterSet = DEFAULT_CHARS ,
25+ className,
26+ ...motionProps
27+ } : TextScrambleProps ) => {
28+ const [ text , setText ] = useState ( children ) ;
29+
30+ useEffect ( ( ) => {
31+ let step = 0 ;
32+ const interval = setInterval ( ( ) => {
33+ let scrambled = "" ;
34+
35+ for ( let i = 0 ; i < children . length ; i ++ ) {
36+ if ( i < step ) {
37+ scrambled += children [ i ] ;
38+ } else if ( children [ i ] === " " ) {
39+ scrambled += " " ;
40+ } else {
41+ scrambled += getRandomChar ( characterSet ) ;
42+ }
43+ }
44+
45+ setText ( scrambled ) ;
46+ step ++ ;
47+
48+ if ( step > children . length ) {
49+ clearInterval ( interval ) ;
50+ setText ( children ) ;
51+ }
52+ } , speed ) ;
53+
54+ return ( ) => clearInterval ( interval ) ;
55+ } , [ children , speed , characterSet ] ) ;
56+
57+ return (
58+ < motion . span className = { className } { ...motionProps } >
59+ { text }
60+ </ motion . span >
61+ ) ;
62+ } ;
You can’t perform that action at this time.
0 commit comments