Last active
August 29, 2015 14:22
-
-
Save hkfoster/9223cc2930a5b68b3778 to your computer and use it in GitHub Desktop.
Headline Typewriter Animation
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
/** | |
* Typewriter.js 0.0.1 | |
* @author Kyle Foster (@hkfoster) | |
* @license MIT (http://www.opensource.org/licenses/mit-license.php/) | |
*/ | |
var typewriter = ( function() { | |
var headline = document.querySelector( '.typewriter' ); | |
if ( !headline ) { return; } | |
/** | |
* Behaves the same as setTimeout except uses requestAnimationFrame() where possible for better performance | |
* @param {function} fn The callback function | |
* @param {int} delay The delay in milliseconds | |
*/ | |
window.requestTimeout = function( fn, delay ) { | |
var start = new Date().getTime(), | |
handle = new Object(); | |
function loop() { | |
var current = new Date().getTime(), | |
delta = current - start; | |
delta >= delay ? fn.call() : handle.value = requestAnimationFrame( loop ); | |
}; | |
handle.value = requestAnimationFrame( loop ); | |
return handle; | |
}; | |
var animationDelay = 2500, | |
typeLettersDelay = 150, | |
selectionDuration = 500, | |
typeAnimationDelay = selectionDuration + 800, | |
headlineWords = headline.querySelectorAll( '.words > .word' ); | |
// Init function | |
function initHeadline() { | |
setupWords( headlineWords ); | |
setupLetters( headlineWords ); | |
pause( headline ); | |
animateHeadline( headline ); | |
} | |
// Initial show/hide of words | |
function setupWords( words ) { | |
for ( var wordIndex = 0; wordIndex < words.length; wordIndex++ ) { | |
hide( words[ wordIndex ] ); | |
show( words[ 0 ] ); | |
} | |
} | |
// Initial wrap/show/hide of letters | |
function setupLetters( words ) { | |
for ( var wordIndex = 0; wordIndex < words.length; wordIndex++ ) { | |
var word = words[ wordIndex ], | |
letters = word.textContent.split( '' ), | |
selected = classie.has( word, 'shown' ); | |
for ( var letterIndex = 0; letterIndex < letters.length; letterIndex++ ) { | |
letters[ letterIndex ] = ( selected ) ? '<span class="shown">' + letters[ letterIndex ] + '</span>': '<span class="hidden">' + letters[ letterIndex ] + '</span>'; | |
} | |
word.innerHTML = letters.join( '' ); | |
} | |
} | |
// Main animation function | |
function animateHeadline( headline ) { | |
requestTimeout( function() { | |
hideWord( headline.querySelector( '.shown' ) ); | |
}, animationDelay ); | |
} | |
// Hide word | |
function hideWord( word ) { | |
var nextWord = takeNext( word ), | |
wordLetters = word.querySelectorAll( 'span' ), | |
parentSpan = word.parentNode; | |
select( parentSpan ); | |
unpause( headline ); | |
requestTimeout( function() { | |
deselect( parentSpan ); | |
hide( word ); | |
for ( var letterIndex = 0; letterIndex < wordLetters.length; letterIndex++ ) { | |
hide( wordLetters[ letterIndex ] ); | |
} | |
}, selectionDuration ); | |
requestTimeout( function() { | |
showWord( nextWord, typeLettersDelay ); | |
}, typeAnimationDelay ); | |
} | |
// Show word | |
function showWord( word, duration ) { | |
showLetter( word.querySelector( 'span' ), word, false, duration ); | |
show( word ); | |
} | |
// Show letter | |
function showLetter( letter, word, bool, duration ) { | |
show( letter ); | |
if ( letter !== letter.parentNode.lastChild ) { | |
requestTimeout( function() { | |
showLetter( letter.nextElementSibling, word, bool, duration ); | |
}, duration ); | |
} else { | |
requestTimeout( function() { | |
pause( headline ); | |
}, 200 ); | |
if ( !bool ) { | |
requestTimeout( function() { | |
hideWord( word ); | |
}, animationDelay ); | |
} | |
} | |
} | |
// Choose next word | |
function takeNext( word ) { | |
return ( word !== word.parentNode.lastChild.previousSibling ? word.nextElementSibling : word.parentNode.firstChild.nextElementSibling ); | |
} | |
// Select | |
function select( elem ) { | |
classie.add( elem, 'selected' ); | |
} | |
// Deselect | |
function deselect( elem ) { | |
classie.remove( elem, 'selected' ); | |
} | |
// Pause | |
function pause( elem ) { | |
classie.add( elem, 'paused' ); | |
} | |
// Unpause | |
function unpause( elem ) { | |
classie.remove( elem, 'paused' ); | |
} | |
// Hide | |
function hide( elem ) { | |
classie.remove( elem, 'shown' ); | |
classie.add( elem, 'hidden' ); | |
} | |
// Show | |
function show( elem ) { | |
classie.remove( elem, 'hidden' ); | |
classie.add( elem, 'shown' ); | |
} | |
// Instantiate | |
initHeadline(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment