Skip to content

Instantly share code, notes, and snippets.

@crazy4groovy
Last active February 17, 2021 21:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crazy4groovy/ca6c81f13c4dffa72c1c57805a457bec to your computer and use it in GitHub Desktop.
Save crazy4groovy/ca6c81f13c4dffa72c1c57805a457bec to your computer and use it in GitHub Desktop.
@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;
}
<div class="container">
<div class="text"></div>
</div>
// ——————————————————————————————————————————————————
// 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