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
|
const useFlicker = (el, val = '_') => { let flickerNode, textNode, intervalInstance, timeoutInstance, typingInstance, initStateInstance
const initFlicker = () => { el.innerHTML = '' flickerNode = document.createElement('span') flickerNode.style.opacity = '0' flickerNode.style.transition = 'opacity 300ms' flickerNode.style.willChange = 'opacity' textNode = document.createElement('span') const span = document.createElement('span') span.appendChild(textNode) span.appendChild(flickerNode) el.appendChild(span) } initFlicker() const setInitialState = () => flickerNode.style.opacity = '0' const setFlickerState = () => flickerNode.style.opacity = '1' const typingHandler = (fn, next = true) => { clearInterval(intervalInstance) fn() setFlickerState() clearTimeout(initStateInstance) initStateInstance = setTimeout(setInitialState, 400) if (next) startFlicker() else flickerNode.innerHTML = '' } const startFlicker = () => { clearTimeout(timeoutInstance) clearInterval(intervalInstance) flickerNode.innerHTML = val intervalInstance = setInterval(() => timeoutInstance = (setFlickerState(), setTimeout(setInitialState, 400)) , 1100) } const closeFlicker = () => { clearInterval(intervalInstance) flickerNode.innerHTML = '' } const clearText = next => typingHandler(() => textNode.innerText = '', next) const pushText = ({ value, duration = 0, easing = x => x, next }) => { if (!value) return const valCount = value.length const runTimeout = (active = 0, beforeTime = 0) => { active = ++active if (active > valCount) return const delay = easing(active / valCount) * duration - beforeTime typingInstance = setTimeout(() => { typingHandler(() => textNode.innerText += value[active - 1], active < valCount || next) runTimeout(active, beforeTime + delay) }, delay) } runTimeout() } const popText = next => typingHandler(() => textNode.innerText = textNode.innerText.slice(0, -1), next)
return { startFlicker, closeFlicker, clearText, pushText, popText } }
export { useFlicker }
|