<div class="container"> <h1 class="heading" data-target-resolver></h1> </div>
* { box-sizing: border-box; } html, body { height: 100%; margin: 0; font-family: 'Unica One', sans-serif; background: #111; } .container { display: flex; align-items: center; justify-content: center; height: 100%; padding: 5rem; } .heading { color: #eee; font-size: 5rem; font-weight: 300; text-transform: uppercase; }
const resolver = { resolve: function resolve(options, callback) { // The string to resolve const resolveString = options.resolveString || options.element.getAttribute('data-target-resolver'); const combinedOptions = Object.assign({}, options, {resolveString: resolveString}); function getRandomInteger(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }; function randomCharacter(characters) { return characters[getRandomInteger(0, characters.length - 1)]; }; function doRandomiserEffect(options, callback) { const characters = options.characters; const timeout = options.timeout; const element = options.element; const partialString = options.partialString; let iterations = options.iterations; setTimeout(() => { if (iterations >= 0) { const nextOptions = Object.assign({}, options, {iterations: iterations - 1}); // Ensures partialString without the random character as the final state. if (iterations === 0) { element.textContent = partialString; } else { // Replaces the last character of partialString with a random character element.textContent = partialString.substring(0, partialString.length - 1) + randomCharacter(characters); } doRandomiserEffect(nextOptions, callback) } else if (typeof callback === "function") { callback(); } }, options.timeout); }; function doResolverEffect(options, callback) { const resolveString = options.resolveString; const characters = options.characters; const offset = options.offset; const partialString = resolveString.substring(0, offset); const combinedOptions = Object.assign({}, options, {partialString: partialString}); doRandomiserEffect(combinedOptions, () => { const nextOptions = Object.assign({}, options, {offset: offset + 1}); if (offset <= resolveString.length) { doResolverEffect(nextOptions, callback); } else if (typeof callback === "function") { callback(); } }); }; doResolverEffect(combinedOptions, callback); } } /* Some GLaDOS quotes from Portal 2 chapter 9: The Part Where He Kills You * Source: http://theportalwiki.com/wiki/GLaDOS_voice_lines#Chapter_9:_The_Part_Where_He_Kills_You */ const strings = [ 'Oh thank god, you\'re alright.', 'You know, being Caroline taught me a valuable lesson. I thought you were my greatest enemy. When all along you were my best friend.', 'The surge of emotion that shot through me when I saved your life taught me an even more valuable lesson: where Caroline lives in my brain.', 'Goodbye, Caroline.', 'You know, deleting Caroline just now taught me a valuable lesson. The best solution to a problem is usually the easiest one. And I\'ll be honest.', 'Killing you? Is hard.', 'You know what my days used to be like? I just tested. Nobody murdered me. Or put me in a potato. Or fed me to birds. I had a pretty good life.', 'And then you showed up. You dangerous, mute lunatic. So you know what?', 'You win.', 'Just go.', 'It\'s been fun. Don\'t come back.', '......' ]; let counter = 0; const options = { // Initial position offset: 0, // Timeout between each random character timeout: 5, // Number of random characters to show iterations: 10, // Random characters to pick from characters: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'x', 'y', 'x', '#', '%', '&', '-', '+', '_', '?', '/', '\\', '='], // String to resolve resolveString: strings[counter], // The element element: document.querySelector('[data-target-resolver]') } // Callback function when resolve completes function callback() { setTimeout(() => { counter ++; if (counter >= strings.length) { counter = 0; } let nextOptions = Object.assign({}, options, {resolveString: strings[counter]}); resolver.resolve(nextOptions, callback); }, 1000); } resolver.resolve(options, callback);