Skip to content

Instantly share code, notes, and snippets.

@sketchpunk
Last active March 15, 2019 15:14
Show Gist options
  • Save sketchpunk/89668a0b179cb576d1631a8c19846d15 to your computer and use it in GitHub Desktop.
Save sketchpunk/89668a0b179cb576d1631a8c19846d15 to your computer and use it in GitHub Desktop.
Timeline Animation - Track and Key Frames
/*
This is a basic framework for Timeline Animations. This example only animates a single float value, but you may build the frame
class to hold any value type, maybe have different Frame objects based on Type, for example quaternions would need an extra step
for interpolation by normalizing the final value where a vector would not need that.
If buidling this in rust or other languages, Maybe generics would be a good use for creating keyframes of different types.
Or you can build a general purpose keyframe that interpolates multiple values at once. Sky's the limit.
*/
// TRACK - COLLECTION OF ORDERED KEYFRAMES
class Track{
constructor(){
this.frames = new Array();
this.value = 0;
}
add( t, v, e=null ){ this.frames.push( new Frame( t, v, e ) ); return this; }
sort(){ this.frames.sort( Track.sort_func ); return this; }
at( t ){
let last = this.frames.length - 1,
v = null,
f, i ;
if( t >= this.frames[ last ].time ){
v = this.frames[ last ].value; // At the end of animation
}else{
for( i=last-1; i > -1; i-- ){
f = this.frames[ i ];
if( f.time == t ){ v = f.value; break; } // Exact time, just get the value
if( t > f.time ){
if( f.value == this.frames[ i+1 ].value )
v = f.value; // incase there is a pause in change, don't try to lerp
else
v = Frame.lerp( f, this.frames[ i+1 ], t ); // lerp the value between the two frames
break;
}
}
}
//console.log( "TRACK AT", t, "Frame", i );
this.value = v;
return v;
}
static sort_func( a, b ){ return (a.time == b.time)? 0 : (a.time < b.time) ? -1 : 1; }
}
// KEY FRAME
class Frame{
constructor( t, v, e=null ){
this.time = t;
this.value = v;
this.easing = e;
}
static lerp( f0, f1, t ){
let n = ( t - f0.time ) / ( f1.time - f0.time );
if( f0.easing ) n = f0.easing( n );
return (1-n) * f0.value + n * f1.value;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment