/* animateText.js jQuery plugin for animating text. Version: 1.0 Github: https://github.com/Lukeas14/animateText.js Author: Justin Lucas (Lukeas14@gmail.com) Copyright (c) 2012 Justin Lucas Licensed under MIT License (https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt) */ ;(function($, window, document, undefined){ function AnimateText(element, textObjects, options, animations){ var self = this; this.$element = $(element); //ul jQuery object this.textObjects = textObjects; this.lastTextObject; //last text object to complete its animation this.repeated = 0; //# of times the animation sequence has repeated //Default options this.defaults = { repeat: true, element: { css: { position: 'relative', overflow: 'hidden', margin: 0, padding: 0, width: function(){ return $(this).parent().width(); }, height: function(){ return $(this).parent().height(); }, 'list-style': 'none' } }, textObject: { css: { position: 'absolute', margin: 0, padding: 0 }, offset: 0, animation: 'explode' }, position: { duration: 1000, easing: 'swing' } }; //Merge default options with user options this.options = $.extend(true, {}, this.defaults, options); //Default animations this.animations = { "fadeIn": { positions: { start: { top: '50%', left: '50%', opacity: 0 }, 0: { opacity: 1, duration: 1200 }, 1: { duration: 1200 }, 2: { opacity: 0, duration: 300 } } }, "fadeOut": { positions: { start: { top: '50%', left: '50%', opacity: 1 }, 0: { duration: 1200 }, 1: { opacity: 0 } } }, "rightToLeft": { positions: { start: { width: '100%', left: '100%', opacity: 0, top: '50%', 'text-align': 'left' }, 0: { left: '25%', opacity: 1, duration: 1200 }, 1: { duration: 1200 }, 2: { opacity: 0, duration: 1200 } } }, "leftToRight": { positions: { start: { width: '100%', right: '100%', opacity: 0, top: '50%', 'text-align': 'right' }, 0: { right: '25%', opacity: 1, duration: 1200 }, 1: { duration: 1200 }, 2: { opacity: 0, duration: 1200 } } }, "explode": { positions: { start: { top: '40%', width: '100%', opacity: 0, 'font-size': '10px', 'text-align': 'center' }, 0: { opacity: 1, duration: 0 }, 1: { top:'-10%', 'font-size': '150px', opacity: 0, duration: 1000 } } }, "implode": { positions: { start: { width: '100%', opacity: 0, top: '0%', 'font-size': '150px', 'text-align': 'center' }, 0: { top: '30%', 'font-size': '40px', opacity: 1, duration: 1000 }, 1: { duration: 1200 }, 2: { opacity: 0, duration: 400 } } } }; //Merge default animations with user animations $.extend(true, this.animations, animations); this.init(); } AnimateText.prototype = { init: function(){ var self = this; //Hide ul element and set css this.$element.hide().css(this.options.element.css); //Start animation as soon as animations and textObjects are loaded. this.loadAnimations(); this.loadTextObjects(function(){ self.$element.show(); self.startAnimation(); }); }, loadAnimations: function(){ var self = this; //Validate every position in every animation $.each(this.animations, function(animationId, animation){ animation.duration = 0; $.each(animation.positions, function(positionId, position){ if(positionId !== "start"){ //Make sure position's duration is set if(typeof(position.duration) !== "number" || position.duration < 0){ position.duration = self.options.position.duration; } //Make sure position's easing property is set if(typeof(position.easing) === "undefined"){ position.easing = self.options.position.easing; } //Calculate the animation's total duration animation.duration += position.duration; } }); }); }, loadTextObjects: function(callback){ var self = this; //Keep track of the animation sequence's total duration totalDuration = 0; //Validate every textObject $.each(this.textObjects, function(textObjectId, textObject){ var textObjectDuration = 0; textObject.id = textObjectId; //Set text object element textObject.$element = self.$element.children("li:eq(" + textObjectId + ")"); //Make sure text object element exists if(!textObject.$element.length){ return; } //Set textObject to its default style textObject.$element.css(self.options.textObject.css).attr('id', textObject.id); //Check for valid animation type if(typeof(textObject.animation) === "undefined" || (typeof(textObject.animation) === "string" && !textObject.animation in self.animations)){ textObject.animation = self.options.textObject.animation; } //Check for valid time offset if(typeof(textObject.offset) !== "number" || textObject.offset < 0){ textObject.offset = self.options.textObject.offset; } if(typeof(textObject.duration) !== "number" || textObject.duration < 0){ textObject.duration = 0; } //Merge textObject's positions with its animation's positions textObject.positions = $.extend(true, {}, self.animations[textObject.animation].positions, textObject.positions); //Calculate textObject duration $.each(textObject.positions, function(positionId, position){ if(positionId !== "start"){ if(typeof(textObject.duration) === "number" && textObject.duration > 0){ position.duration = (position.duration / self.animations[textObject.animation].duration) * textObject.duration; } else{ textObjectDuration += position.duration; } } }); if(textObjectDuration > 0){ textObject.duration = textObjectDuration; } //Determine if this textObject will be last to complete its animation if((textObject.offset + textObject.duration) > totalDuration){ totalDuration = (textObject.offset + textObject.duration); self.lastTextObject = textObject.id; } textObject.status = 'ready'; }); callback(); }, startAnimation: function(){ var self = this; $.each(this.textObjects, function(textObjectId, textObject){ //Set textObject to its start position textObject.$element.css(textObject.positions.start); //Start textObject's animation after it's offset time has passed setTimeout(function(){ self.animateTextObject(textObject.id, 0); }, textObject.offset); }); }, stopAnimation: function(){ this.$element.children("li").stop(); }, animateTextObject: function(textObjectId, animationPosition){ var self = this, textObject = this.textObjects[textObjectId], animation = this.animations[textObject.animation], test = function(){ var to = textObject; console.log(to); return 'hey'; }; //Finally, animate the textObject textObject.$element.animate( textObject.positions[animationPosition], textObject.positions[animationPosition].duration, textObject.positions[animationPosition].easing, function(){ //Does this animation have another position? If so animate it. if(typeof(textObject.positions[(animationPosition + 1)]) !== "undefined"){ self.animateTextObject(textObject.id, (animationPosition + 1)); } //Is this the last text object in the group? else if(textObject.id === self.lastTextObject){ self.stopAnimation(); //Repeat animations if repeat option is set to true or we're still under the set repeat limit if(self.options.repeat === true || (typeof(self.options.repeat) === "number" && self.repeated < self.options.repeat)){ self.startAnimation(); self.repeated++; } } } ); } }; $.fn.animateText = function(textObjects, options, animations){ return this.each(function(){ new AnimateText(this, textObjects, options, animations); }); }; })( jQuery );