UNPKG

@twistezo/react-text-scramble

Version:
144 lines (142 loc) 3.82 kB
// src/constants.ts var DEFAULT_LETTER_SPEED = 5; var DEFAULT_NEXT_LETTER_SPEED = 100; var DEFAULT_PAUSE_TIME = 1500; var DEFAULT_PAUSED = false; var SYMBOLS = "!<>-_\\/[]{}—=+*^?#".split(""); // src/utils.ts var randomItem = (array) => array[Math.floor(Math.random() * array.length)]; var nextItem = (array, currentItem) => { const currentIndex = array.indexOf(currentItem); const bound = array.length; const nextIndex = (currentIndex + bound + 1) % bound; return array[nextIndex]; }; // src/TextScrambleAnimator.ts class TextScrambleAnimator { bakeLetterInterval = null; bakeTextInterval = null; currentText; displayedText; element; leftIndexes = []; letterSpeed; nextLetterSpeed; paused; pauseTime; pauseTimeout = null; texts; constructor(element, options) { this.element = element; this.texts = options.texts; this.letterSpeed = options.letterSpeed ?? DEFAULT_LETTER_SPEED; this.nextLetterSpeed = options.nextLetterSpeed ?? DEFAULT_NEXT_LETTER_SPEED; this.pauseTime = options.pauseTime ?? DEFAULT_PAUSE_TIME; this.paused = options.paused ?? DEFAULT_PAUSED; this.currentText = this.texts[0]; this.displayedText = this.initSymbols(); this.render(); if (!this.paused) { this.animate(); } } destroy() { this.clearAllIntervals(); } pause() { this.paused = true; if (this.pauseTimeout) { clearTimeout(this.pauseTimeout); this.pauseTimeout = null; } } play() { this.paused = false; this.clearAllIntervals(); this.animate(); } reset() { this.clearAllIntervals(); this.currentText = this.texts[0]; this.displayedText = this.initSymbols(); this.render(); this.leftIndexes = []; if (!this.paused) { this.animate(); } } setTexts(texts) { this.texts = texts; this.reset(); } animate() { this.bakeText(); } bakeLetter() { this.bakeLetterInterval = setInterval(() => { if (!this.paused) { const updatedText = []; this.currentText.split("").forEach((char, i) => { if (!this.leftIndexes.includes(i)) { updatedText[i] = this.currentText[i]; return; } updatedText[i] = randomItem(SYMBOLS); }); this.displayedText = updatedText; this.render(); } }, this.letterSpeed); } bakeText() { this.leftIndexes = this.currentText.split("").map((_, i) => i); this.bakeLetter(); this.bakeTextInterval = setInterval(() => { if (!this.paused) { if (this.leftIndexes.length === 0) { this.clearAllIntervals(); this.pauseTimeout = setTimeout(() => { this.currentText = nextItem(this.texts, this.currentText); this.displayedText = this.initSymbols(); this.render(); this.animate(); }, this.pauseTime); return; } this.leftIndexes.shift(); } }, this.nextLetterSpeed); } clearAllIntervals() { if (this.bakeLetterInterval) { clearInterval(this.bakeLetterInterval); this.bakeLetterInterval = null; } if (this.bakeTextInterval) { clearInterval(this.bakeTextInterval); this.bakeTextInterval = null; } if (this.pauseTimeout) { clearTimeout(this.pauseTimeout); this.pauseTimeout = null; } } initSymbols() { return Array(this.currentText.length).fill(0).map(() => randomItem(SYMBOLS)); } render() { this.element.textContent = this.displayedText.join(""); } } function createTextScramble(element, options) { return new TextScrambleAnimator(element, options); } export { createTextScramble, TextScrambleAnimator, SYMBOLS, DEFAULT_PAUSE_TIME, DEFAULT_PAUSED, DEFAULT_NEXT_LETTER_SPEED, DEFAULT_LETTER_SPEED };