Last active
August 29, 2015 14:19
-
-
Save rogeruiz/f35b498fa80d07b1dc1f to your computer and use it in GitHub Desktop.
Animation Engine used on How We Work for CISofRichmond
This file contains hidden or 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 { $, RSVP, _, Snap, mina, help } from 'util'; | |
| var Fn = function() { | |
| var fn = this; | |
| this.DELAY_START = 250; | |
| this.ANIMATION_DURATION = 550; | |
| this.CIRCLE_ROTATION_DURATION = 50000; | |
| this.el = { | |
| container: '.js-hww-container' | |
| }; | |
| this.ctx = { | |
| 'studentDropout': { | |
| init: function() { | |
| var svg = this.getSvg(); | |
| this.books = fn.getAllBooks( svg ); | |
| }, | |
| animate: function() { | |
| var ctx = this; | |
| window.setTimeout( function() { | |
| fn.toppleBooks( ctx.books ); | |
| }, fn.DELAY_START ); | |
| } | |
| }, | |
| 'siteCoordinator': { | |
| init: function() { | |
| var svg = this.getSvg(); | |
| this.coordinator = fn.getCoordinator( svg ); | |
| this.coordinator.attr( { | |
| transform: 'translate(50, 0)', | |
| opacity: 0 | |
| } ); | |
| }, | |
| animate: function() { | |
| var ctx = this; | |
| window.setTimeout(function() { | |
| ctx.coordinator.animate( { | |
| transform: 'translate(0, 0)', | |
| opacity: 1 | |
| }, fn.ANIMATION_DURATION ); | |
| }, fn.DELAY_START); | |
| } | |
| }, | |
| 'collaborativeEffort': { | |
| init: function() { | |
| var svg = this.getSvg(); | |
| this.mainCircle = fn.getMainCircle( svg ); | |
| this.icons = fn.getAllIcons( svg, 'circle' ); | |
| _.forEach(this.icons, function( icon ) { | |
| icon.attr({ | |
| opacity: 0.15 | |
| }); | |
| }); | |
| }, | |
| animate: function() { | |
| var ctx = this; | |
| window.setTimeout( function() { | |
| fn.fadeIn(ctx.icons, function() { | |
| fn.rotateMainCircle( ctx.mainCircle ); | |
| }); | |
| }, fn.DELAY_START ); | |
| } | |
| }, | |
| 'integratedServices': { | |
| init: function() { | |
| var svg = this.getSvg(); | |
| this.mainCircle = fn.getMainCircle( svg ); | |
| this.icons = fn.getAllIcons( svg, 'circle' ); | |
| }, | |
| animate: function() { | |
| var ctx = this; | |
| window.setTimeout( function() { | |
| fn.bounceIn(ctx.icons, function() { | |
| fn.rotateMainCircle( ctx.mainCircle ); | |
| }); | |
| }, fn.DELAY_START ); | |
| } | |
| }, | |
| 'monitorTrackServices': { | |
| init: function() { | |
| var svg = this.getSvg(); | |
| this.icons = fn.getAllIcons( svg, 'track' ); | |
| _.forEach(this.icons, function( icon ) { | |
| var cover = icon.select( '#cis-circle-cover' ); | |
| var mark = icon.select( '#cis-check-mark' ); | |
| cover.attr({ | |
| opacity: 0 | |
| }); | |
| var len = mark.getTotalLength(); | |
| mark.attr({ | |
| 'stroke-dasharray': len + ' ' + len, | |
| 'stroke-dashoffset': len, | |
| opacity: 0 | |
| }); | |
| }); | |
| }, | |
| animate: function() { | |
| var ctx = this; | |
| window.setTimeout( function() { | |
| fn.animateTracks( ctx.icons ); | |
| }, fn.DELAY_START ); | |
| } | |
| } | |
| }; | |
| return this; | |
| }; | |
| Fn.prototype.getMainCircle = function( svg ) { | |
| return svg.select( '#cis-circle-main' ); | |
| }; | |
| Fn.prototype.getCapIcon = function( svg ) { | |
| return svg.select( '#cis-cap' ); | |
| }; | |
| Fn.prototype.getFamilyIcon = function( svg ) { | |
| return svg.select( '#cis-family' ); | |
| }; | |
| Fn.prototype.getPlateIcon = function( svg ) { | |
| return svg.select( '#cis-plate' ); | |
| }; | |
| Fn.prototype.getBooksIcon = function( svg ) { | |
| return svg.select( '#cis-books' ); | |
| }; | |
| Fn.prototype.getHandsIcon = function( svg ) { | |
| return svg.select( '#cis-hands' ); | |
| }; | |
| Fn.prototype.getCoordinator = function( svg ) { | |
| return svg.select( '#cis-coordinator' ); | |
| }; | |
| Fn.prototype.getAllIcons = function(svg, order) { | |
| if ( 'circle' === order ) { | |
| return [ | |
| this.getCapIcon( svg ), | |
| this.getPlateIcon( svg ), | |
| this.getBooksIcon( svg ), | |
| this.getFamilyIcon( svg ), | |
| this.getHandsIcon( svg ) | |
| ]; | |
| } else if ( 'track' === order ) { | |
| return [ | |
| this.getPlateIcon( svg ), | |
| this.getBooksIcon( svg ), | |
| this.getFamilyIcon( svg ), | |
| this.getHandsIcon( svg ), | |
| this.getCapIcon( svg ) | |
| ]; | |
| } | |
| }; | |
| Fn.prototype.getAllBooks = function( svg ) { | |
| var bookRange = _.range( 4 ); | |
| return _.map( bookRange, function( book, idx ) { | |
| var path = svg.select( '#cis-book-' + ( idx + 1 ) ); | |
| var bounds = path.getBBox(); | |
| var width = bounds.width; | |
| var x = bounds.x; | |
| var cx = width + x; | |
| var height = bounds.height; | |
| var y = bounds.y; | |
| var cy = height + y; | |
| var queue = []; | |
| switch ( idx ) { | |
| case 0: | |
| queue.push( `rotate(90, ${cx}, ${cy})` ); | |
| break; | |
| case 1: | |
| queue.push( `rotate(45, ${cx}, ${cy})` ); | |
| queue.push( `rotate(90, ${cx}, ${cy}), translate(${-width}, 0)` ); | |
| break; | |
| default: | |
| queue.push( `rotate(35, ${cx}, ${cy})` ); | |
| } | |
| return { | |
| svgPath: path, | |
| animations: queue | |
| }; | |
| } ); | |
| }; | |
| Fn.prototype.rotateMainCircle = function( circle ) { | |
| var fn = this; | |
| var cx = circle.attr( 'cx' ); | |
| var cy = circle.attr( 'cy' ); | |
| var r = circle.attr( 'r' ); | |
| circle.animate( { | |
| transform: `rotate(360, ${cx}, ${cy})` | |
| }, fn.CIRCLE_ROTATION_DURATION, function() { | |
| circle.attr( { | |
| transform: `rotate(0, ${cx}, ${cy})` | |
| } ); | |
| fn.rotateMainCircle( circle ); | |
| } ); | |
| }; | |
| Fn.prototype.toppleBooks = function( books, done ) { | |
| var fn = this; | |
| var halfTime = fn.ANIMATION_DURATION * 0.5; | |
| if ( books.length > 0 ) { | |
| var book = books.shift(); | |
| if ( book.animations.length > 1 ) { | |
| book.svgPath.animate( { | |
| transform: book.animations[ 0 ] | |
| }, halfTime, function() { | |
| book.svgPath.animate( { | |
| transform: book.animations[ 1 ] | |
| }, halfTime, function() { | |
| fn.toppleBooks(books, done); | |
| } ); | |
| } ); | |
| } else { | |
| book.svgPath.animate( { | |
| transform: book.animations[ 0 ] | |
| }, fn.ANIMATION_DURATION, function() { | |
| fn.toppleBooks( books, done ); | |
| } ); | |
| } | |
| } else { | |
| if ( $.isFunction( done ) ) { | |
| done(); | |
| } | |
| } | |
| }; | |
| Fn.prototype.animateTracks = function( icons, done ) { | |
| var fn = this; | |
| if ( icons.length > 0 ) { | |
| var icon = icons.shift(); | |
| var cover = icon.select( '#cis-circle-cover' ); | |
| var mark = icon.select( '#cis-check-mark' ); | |
| cover.animate( { | |
| opacity: 0.8 | |
| }, fn.ANIMATION_DURATION, function() { | |
| mark.animate( { | |
| opacity: 1, | |
| 'stroke-dashoffset': 10 | |
| }, fn.ANIMATION_DURATION, function() { | |
| fn.animateTracks(icons, done); | |
| } ); | |
| } ); | |
| } else { | |
| if ( $.isFunction( done ) ) { | |
| done(); | |
| } | |
| } | |
| }; | |
| Fn.prototype.fadeIn = function( items, done ) { | |
| var fn = this; | |
| if ( items.length > 0 ) { | |
| var item = items.shift(); | |
| item.animate( { | |
| opacity: 1 | |
| }, fn.ANIMATION_DURATION, function() { | |
| fn.fadeIn( items, done ); | |
| } ); | |
| } else { | |
| if ( $.isFunction( done ) ) { | |
| done(); | |
| } | |
| } | |
| }; | |
| Fn.prototype.bounceIn = function( items, done ) { | |
| var fn = this; | |
| var quarterTime = fn.ANIMATION_DURATION * 0.25; | |
| if ( items.length > 0 ) { | |
| var item = items.shift(); | |
| var scaleFactor = 1.25; | |
| var x = item.select( 'circle' ).attr( 'cx' ) * ( scaleFactor - 1 ); | |
| var y = item.select( 'circle' ).attr( 'cy' ) * ( scaleFactor - 1 ); | |
| item.animate( { | |
| transform: `translate(${-x}, ${-y}) scale(${scaleFactor})`, | |
| opacity: 0.85 | |
| }, quarterTime, function() { | |
| item.animate( { | |
| transform: 'scale(1)', | |
| opacity: 1 | |
| }, fn.ANIMATION_DURATION, mina.bounce, function() { | |
| fn.bounceIn( items, done ); | |
| } ); | |
| } ); | |
| } else { | |
| if ( $.isFunction( done ) ) { | |
| done(); | |
| } | |
| } | |
| }; | |
| var Engine = function( name ) { | |
| var component = this; | |
| this.fn = new Fn(); | |
| this.animated = false; | |
| this.name = name; | |
| this.ctx = this.fn.ctx[ name ]; | |
| this.ctx.getContainer = function() { | |
| return $( '.js-' + help.dasherize( name ) ); | |
| }; | |
| this.ctx.getSvg = function() { | |
| return Snap( '#cis-' + help.dasherize( name ) ); | |
| }; | |
| this.ctx.getParentContainer = function() { | |
| return this.getContainer().parents( component.fn.el.container ); | |
| }; | |
| this.ctx.getThreshold = function() { | |
| return this.getParentContainer().offset().top - ( this.getContainer().height() * 0.5 ); | |
| }; | |
| this.ctx.init(); | |
| this.recalculateSize(); | |
| return this; | |
| }; | |
| Engine.prototype.triggerAnimation = function() { | |
| if ( this.animated ) { | |
| return; | |
| } | |
| if ( $(window).scrollTop() >= this.ctx.getThreshold() ) { | |
| this.ctx.animate(); | |
| this.animated = true; | |
| } | |
| }; | |
| Engine.prototype.recalculateSize = function() { | |
| var $container = this.ctx.getContainer(); | |
| $container.find( 'svg' ).css({ | |
| width: $container.width(), | |
| height: $container.width() | |
| }); | |
| }; | |
| export default Engine; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment