Last active
August 14, 2021 11:09
-
-
Save KajSzy/8ce3ec176d69e7e58f46fe54f227fa45 to your computer and use it in GitHub Desktop.
Animated text loader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as React from 'react' | |
| type LoaderProps = { | |
| label?: string | |
| animationIteration?: number | |
| animationDelay?: number | |
| stayOnLabelFor?: number | |
| loopAnimation?: boolean | |
| } | |
| const ALL_POSSIBLE_CHARS = | |
| 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()_+-={}[]:";\'<>?,./|\\' | |
| const getRandomString = () => | |
| ALL_POSSIBLE_CHARS[Math.floor(Math.random() * ALL_POSSIBLE_CHARS.length)] | |
| const createArrayOfChars = (label: string, animationIteration: number) => | |
| label.split('').map((letter) => { | |
| const arr: string[] = [] | |
| for (let i = 0; i < animationIteration; i++) { | |
| let s = getRandomString() | |
| while (arr.includes(s)) { | |
| s = getRandomString() | |
| } | |
| arr.push(getRandomString()) | |
| } | |
| arr.push(letter) | |
| return arr | |
| }) | |
| const Loader: React.FC<LoaderProps> = ({ | |
| label = 'Loading', | |
| animationDelay = 75, | |
| animationIteration = 35, | |
| stayOnLabelFor = 2000, | |
| loopAnimation = true, | |
| }) => { | |
| const [, forceUpdate] = React.useReducer((x) => x + 1, 0) | |
| const indexRef = React.useRef(0) | |
| const intervalRef = React.useRef(0) | |
| const iterableStrings = React.useMemo( | |
| () => createArrayOfChars(label, animationIteration), | |
| [animationIteration] | |
| ) | |
| const setInterval = () => { | |
| intervalRef.current = window.setInterval(bumpIndex, animationDelay) | |
| } | |
| const bumpIndex = () => { | |
| indexRef.current = | |
| indexRef.current <= animationIteration ? indexRef.current + 1 : 0 | |
| if (indexRef.current === animationIteration) { | |
| window.clearInterval(intervalRef.current) | |
| loopAnimation && | |
| window.setTimeout(() => { | |
| indexRef.current = 0 | |
| setInterval() | |
| }, stayOnLabelFor) | |
| } | |
| forceUpdate() | |
| } | |
| React.useEffect(() => { | |
| setInterval() | |
| return () => { | |
| window.clearInterval(intervalRef.current) | |
| } | |
| }, []) | |
| return <div>{iterableStrings.map((c) => c[indexRef.current])}</div> | |
| } | |
| Loader.displayName = 'Loader' | |
| export default Loader |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment