Skip to content

Instantly share code, notes, and snippets.

@KajSzy
Last active August 14, 2021 11:09
Show Gist options
  • Select an option

  • Save KajSzy/8ce3ec176d69e7e58f46fe54f227fa45 to your computer and use it in GitHub Desktop.

Select an option

Save KajSzy/8ce3ec176d69e7e58f46fe54f227fa45 to your computer and use it in GitHub Desktop.
Animated text loader
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