Created
October 21, 2018 14:23
-
-
Save peterb0yd/4585b523c7168c451fb0a8ab58dbdfa3 to your computer and use it in GitHub Desktop.
A file for creating dynamically typed text using plain HTML and vanilla Javascript
This file contains 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
/** | |
* This module is used to simulate text typing in the DOM | |
* | |
*/ | |
export default class Typer { | |
/** | |
* @func constructor | |
* @param el: dom element | |
* @param words: words to iterate | |
* @param typespeed: speed the each char will be 'typed' | |
* @description: initializes the Typer object | |
*/ | |
constructor(el, words, typespeed = 100) { | |
this.el = el | |
this.words = words | |
this.typespeed = typespeed | |
this.interval = null | |
this.timeouts = [] | |
this.isAnimationRunning = false | |
onFocusHandler(this) | |
} | |
/** | |
* @func startAnimation | |
* @description: starts an infinite loop animating through each word | |
*/ | |
startAnimation() { | |
this.isAnimationRunning = true | |
const delayTime = this.words.length * 2000 | |
const typingTime = this.words.map(w => w.split('').length * 2).reduce(getSum) | |
const totalTime = typingTime * this.typespeed + delayTime | |
this.interval = setInterval(this.runAnimation.bind(this), totalTime) | |
this.runAnimation() | |
} | |
/** | |
* @func runAnimation | |
* @description: runs the full typing animation once. adds and removes | |
* the text to and from the dom element's HTML | |
*/ | |
runAnimation() { | |
let wordTime = 0 | |
this.words.map(word => { | |
this.timeouts.push(setTimeout(async () => { | |
await this.typeText(word) | |
await delay(this, 1000) | |
await this.clearText() | |
await delay(this, 1000) | |
}, wordTime)) | |
wordTime += word.split('').length * this.typespeed * 2 + 2000 | |
}) | |
} | |
/** | |
* @func stopAnimation | |
* @description: starts an infinite loop animating through each word | |
*/ | |
async stopAnimation() { | |
clearInterval(this.interval) | |
this.timeouts.map(t => clearTimeout(t)) | |
this.el.innerText = '' | |
await delay(this, 1000) | |
} | |
/** | |
* @func typeText | |
* @param word: String word to type | |
* @description: adds one char at a time within the dom's elements HTL | |
*/ | |
async typeText(word) { | |
return new Promise(resolve => { | |
const chars = word.split('') | |
let charTime = 0 | |
chars.map((char, i) => { | |
charTime += this.typespeed | |
this.timeouts.push(setTimeout(() => { | |
this.el.innerText += char | |
if (i === chars.length - 1) resolve() | |
}, charTime)) | |
}) | |
}) | |
} | |
/** | |
* @func clearText | |
* @description: removes one char at a time within the dom element's HTML | |
*/ | |
async clearText() { | |
return new Promise((resolve, reject) => { | |
const innerText = this.el.innerText | |
const chars = innerText.split('') | |
let charTime = 0 | |
chars.map((char, i) => { | |
charTime += this.typespeed | |
this.timeouts.push(setTimeout(() => { | |
this.el.innerText = innerText.substring(0, this.el.innerText.length - 1) | |
if (i === chars.length - 1) resolve() | |
}, charTime)) | |
}) | |
}) | |
} | |
} | |
/** | |
* @func delay | |
* @param self: the Typer instance | |
* @param t: the delay time length in milliseconds | |
* @description: delays a function | |
*/ | |
const delay = async (self, t) => { | |
return new Promise((resolve, reject) => { | |
self.timeouts.push(setTimeout(() => resolve(), t)) | |
}) | |
} | |
/** | |
* @func getSum | |
* @param t: the total sum | |
* @param n: additional number to add to sum | |
* @description: gets a sum from an array of numbers | |
*/ | |
const getSum = (t, n) => t + n | |
/** | |
* @func onFocusHandler | |
* @param self: the Typer instance | |
* @description: handles the user clicking out of the webpage or switching tabs | |
*/ | |
const onFocusHandler = self => { | |
window.tabIndex = 0 | |
window.onfocus = async () => { | |
await self.stopAnimation() | |
if (self.isAnimationRunning) | |
self.startAnimation() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment