diff options
Diffstat (limited to 'makima/frontend/src/hooks/useTextScramble.ts')
| -rw-r--r-- | makima/frontend/src/hooks/useTextScramble.ts | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/makima/frontend/src/hooks/useTextScramble.ts b/makima/frontend/src/hooks/useTextScramble.ts new file mode 100644 index 0000000..bb3f365 --- /dev/null +++ b/makima/frontend/src/hooks/useTextScramble.ts @@ -0,0 +1,52 @@ +import { useState, useCallback, useRef } from "react"; + +const GLYPHS = "▒▓░█#@*+:-/[]{}<>_"; + +export function useTextScramble(originalText: string) { + const [displayText, setDisplayText] = useState(originalText); + const timerRef = useRef<ReturnType<typeof setInterval> | null>(null); + const iterationRef = useRef(0); + + const scramble = useCallback(() => { + // Clear any existing animation + if (timerRef.current) { + clearInterval(timerRef.current); + } + + iterationRef.current = 0; + + timerRef.current = setInterval(() => { + const text = originalText; + const iteration = iterationRef.current; + + const display = text + .split("") + .map((char, index) => { + if (index < iteration) return char; + return GLYPHS.charAt(Math.floor(Math.random() * GLYPHS.length)); + }) + .join(""); + + setDisplayText(display); + iterationRef.current += 1; + + if (iteration > text.length + 2) { + if (timerRef.current) { + clearInterval(timerRef.current); + timerRef.current = null; + } + setDisplayText(originalText); + } + }, 26); + }, [originalText]); + + const reset = useCallback(() => { + if (timerRef.current) { + clearInterval(timerRef.current); + timerRef.current = null; + } + setDisplayText(originalText); + }, [originalText]); + + return { displayText, scramble, reset }; +} |
