Skip to content

Instantly share code, notes, and snippets.

@timmywil
Created May 28, 2011 20:13
Show Gist options
  • Save timmywil/997191 to your computer and use it in GitHub Desktop.
Save timmywil/997191 to your computer and use it in GitHub Desktop.
Oldschool Keyframes in jQuery
(function( $ ) {
$.fn.keyframe = function(){
if (arguments.length == 0) {
return this;
}
var self = this,
args = Array.prototype.slice.call( arguments ),
// List of keyframes
anim = args[0],
// Capture easing option
default_easing = args[1] || "linear",
// Stores object keys in numerical order
keys = [], key_len,
// Stores various animations to be executed
queue = [],
undefined,
k, n, l;
// Grab all the object key names
for ( k in anim ) {
keys.push(
// Allow use of 'start' instead of 0
(k == "start") ? 0 : parseInt( k )
);
}
// Sort the object's key names in numerical ascending order
keys.sort(function( a, b ) {
return ( a < b ) ? -1 : 1;
});
// Loop through all the keyframes, and build of queue of animations
for ( n = 0, l = keys.length; n < l; n++ ) {
(function( n ) {
var time = keys[ n ], // End-time
last_time = ( n > 0 ) ? keys[ n - 1 ] : 0, // Previous end-time
length = time - last_time, // Minimum duration of animation
batch, // Hold potential animations for this keyframe
prop,
prev, n, easing, value,
batch_name, a;
// If the time is 0 don't animate, just set it
if ( time === 0 ) {
self.stop( true, true ).css( anim["start"] );
// If this is the first non-zero keyframe, just queue up whatever
// is listed, instead of all the brouhaha below
} else if ( (n === 0) || (last_time === 0) ) {
queue.push({
start: 0,
end: time,
style: anim[ time ],
easing: default_easing
});
// Otherwise, go through each of this keyframe's properties, building
// up the necessary animation(s)
} else {
batch = {};
// Loop through keyframe's declared properties
for ( prop in anim[time] ) {
if( !anim[ time ].hasOwnProperty( prop ) ) {
continue;
}
prev = 0;
n = queue.length;
easing = default_easing;
value = anim[ time ][ prop ];
// If value is an array with easing, adjust stuff accordingly
if ( value.constructor.toString().match(/Array/) ) {
easing = value[ 1 ];
value = value[ 0 ];
}
// Find the last time this property was specified, default to 0
while ( n-- ) {
if ( !$.isFunction( queue[n] ) && queue[ n ][ "style" ][ prop ] != undefined ) {
prev = queue[ n ].end;
break;
}
}
// Combine animations with same time and easing, else make a new one
batch_name = prev + '-' + easing;
if ( batch[ batch_name ] === undefined ) {
batch[ batch_name ] = {
start: prev,
end: time,
style: {},
easing: easing
};
}
// Add in property
batch[ batch_name ][ "style" ][ prop ] = value;
}
// Add all animations from current batch in to queue
for ( a in batch ) {
queue.push( batch[a] );
}
}
})( n );
}
// Abuse jQuery.animate's magical queing properties
self.animate({ delay: 1 }, 0, function() {
// Loop through queue of animations, and invoke them all
// using jQuery's built-in `animate`, and `setTimeout`
for ( n = 0, l = queue.length; n < l; n++ ) {
(function( n ) {
var anim = queue[ n ];
self.animate({ delay: 1 }, { queue: false, duration: anim.start, complete: function() {
self.animate( anim.style, { duration: (anim.end - anim.start), easing: anim.easing, queue: false } );
}});
})( n );
}
self.animate( { delay: 1 }, queue[queue.length - 1].end );
});
return this;
};
})( jQuery );
// ============ Example ==============
// function r() { return Math.round( 50 * Math.random() ); }
// elem.keyframe({
// start: {
// top: 90 - r(), left: '-5%'
// },
// 8500: {
// top: 90 + r()
// },
// 16000: {
// top: 90 - r()
// },
// 24995: {
// top: 120 + r(), left: ['105%', 'linear']
// }
// }, 'easeInOutSine');
@hbarone
Copy link

hbarone commented Jun 14, 2011

I wrote this html code based on your example, but it did not work:

html:
div style="border-color:silver; border-style:solid; width:50px; height:50px; position:relative" id="box"
javascript:
$("#box").keyframe({
start: {
top: 90 , left: ['20', 'linear']
},
8500: {
top: 300, left: ['200', 'linear']
}
}, 'easeInOutSine');

@timmywil
Copy link
Author

I haven't released this really, but it works for me. Make sure you have the easing plugin as well if you're going to use an easing function.

@hbarone
Copy link

hbarone commented Jun 14, 2011

Yes, I have it
I wrote this simple html:
http://www.patrociniocoletivo.com.br/teste/jquery/quadro-chave-teste.html
thanks for help !!

@timmywil
Copy link
Author

timmywil commented Jun 14, 2011 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment