Last active
February 17, 2021 21:34
-
-
Save crazy4groovy/ca6c81f13c4dffa72c1c57805a457bec to your computer and use it in GitHub Desktop.
text Scramble effect -- see https://codepen.io/crazy4groovy/pen/oNxbJdv , https://tobiasahlin.com/moving-letters/
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
@import 'https://fonts.googleapis.com/css?family=Roboto+Mono:100'; | |
html, | |
body { | |
font-family: 'Roboto Mono', monospace; | |
background: #212121; | |
height: 100%; | |
} | |
.container { | |
height: 100%; | |
width: 100%; | |
justify-content: center; | |
align-items: center; | |
display: flex; | |
} | |
.text { | |
font-weight: 100; | |
font-size: 28px; | |
color: #fafafa; | |
} | |
.dud { | |
color: #757575; | |
} |
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
<div class="container"> | |
<div class="text"></div> | |
</div> |
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
// —————————————————————————————————————————————————— | |
// TextScramble | |
// —————————————————————————————————————————————————— | |
class TextScramble { | |
constructor(el) { | |
this.el = el; | |
this.chars = "!<>-_\\/[]{}—=+*^?#________"; | |
this.update = this.update.bind(this); | |
} | |
setText(newText) { | |
const oldText = this.el.innerText; | |
const length = Math.max(oldText.length, newText.length); | |
const promise = new Promise((resolve) => (this.resolve = resolve)); | |
this.queue = []; | |
for (let i = 0; i < length; i++) { | |
const fromC = oldText[i] || ""; | |
const toC = newText[i] || ""; | |
const startF = Math.floor(Math.random() * 40); | |
const endF = startF + Math.floor(Math.random() * 40); | |
this.queue.push({ fromC, toC, startF, endF }); | |
} | |
cancelAnimationFrame(this.frameRequest); | |
this.frame = 0; | |
this.update(); | |
return promise; | |
} | |
update() { | |
let output = ""; | |
let complete = 0; | |
for (let i = 0, n = this.queue.length; i < n; i++) { | |
let { fromC, toC, startF, endF, char } = this.queue[i]; | |
if (this.frame >= endF) { | |
complete++; | |
output += toC; | |
} else if (this.frame >= startF) { | |
if (!char || Math.random() < 0.5) { | |
this.queue[i].char = this.randomChar(); | |
char = this.queue[i].char; | |
} | |
output += `<span class="dud">${char}</span>`; | |
} else { | |
output += fromC; | |
} | |
} | |
this.el.innerHTML = output; | |
if (complete === this.queue.length) { | |
this.resolve(); | |
return; | |
} | |
this.frameRequest = requestAnimationFrame(this.update); | |
this.frame++; | |
} | |
randomChar() { | |
return this.chars[Math.floor(Math.random() * this.chars.length)]; | |
} | |
} | |
// —————————————————————————————————————————————————— | |
// Example | |
// —————————————————————————————————————————————————— | |
const phrases = [ | |
"Neo,", | |
"sooner or later", | |
"you're going to realize", | |
"just as I did", | |
"that there's a difference", | |
"between knowing the path", | |
"and walking the path" | |
]; | |
const el = document.querySelector(".text"); | |
const fx = new TextScramble(el); | |
let counter = 0; | |
const tick = () => { | |
fx.setText(phrases[counter]).then(() => { | |
setTimeout(tick, 800); | |
}); | |
counter = (counter + 1) % phrases.length; | |
}; | |
tick(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment