Last active
March 15, 2019 15:14
-
-
Save sketchpunk/89668a0b179cb576d1631a8c19846d15 to your computer and use it in GitHub Desktop.
Timeline Animation - Track and Key Frames
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
/* | |
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