Last active
August 29, 2015 14:23
-
-
Save zebulonj/3a6f8519d9be5e12dcd1 to your computer and use it in GitHub Desktop.
Flux + React Animation: Academic to Implementation
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
'use strict'; | |
/** | |
* Convenience method to get current time. | |
* | |
* @returns {Integer} Current time in milliseconds since Epoch. | |
*/ | |
function now() { | |
return ( new Date() ).getTime(); | |
} | |
/** | |
* Abstract function to execute code on the next animation frame. In practice this method would likely be implemented | |
* using `window.requestAnimationFrame()` or its equivalent. | |
* | |
* @param fn {Function} | |
*/ | |
function frame( fn ) { | |
// Execute `fn` on next animation frame. | |
} | |
/** | |
* Implements a generalized animation loop, on an individual property, "rendering" state changes from state `a` to | |
* state `b` over a specified duration. | |
* | |
* @param a {Number} Initial state. | |
* @param b {Number} Final state. | |
* @param duration {Integer} Animation duration in milliseconds. | |
* | |
* @returns {Function} Returns a function that, if called, will cancel the animation. | |
*/ | |
function animate( a, b, duration ) { | |
const start = now(); | |
let cancelled = false; | |
/** | |
* Abstract render method. In application, would be replaced with specific code to update display based | |
* on incremental state updates. | |
* | |
* @param state {Number} Current state. | |
*/ | |
function render( state ) { | |
console.log( "Render:", state ); | |
// Render current state to display. | |
} | |
/** | |
* Converts specified time to animation progress from 0.0 to 1.0. | |
* | |
* @param time {Integer} Current frame time in milliseconds since Epoch. See `now()`, above. | |
* @returns {number} Progress from 0.0 (start) to 1.0 (end). | |
*/ | |
function progress( time ) { | |
return Math.min( 1, ( time - start ) / duration ); | |
} | |
/** | |
* Uses animation parameters (`a`, `b`, and `duration`) to calculate the state for the current animation frame, | |
* and passes that value to the `render()` function. If the animation is not complete, schedules next update | |
* via `frame()`. | |
*/ | |
function update() { | |
if ( cancelled ) return; | |
let p = progress( now() ); | |
let state = a + ( p * ( b - a ) ); | |
render( state ); | |
if ( p < 1 ) { | |
frame( update ); | |
} | |
} | |
// Start the animation loop. | |
frame( update ); | |
return function cancel() { | |
return ( cancelled = true ); | |
}; | |
} | |
animate( 0, 1, 1000 ); | |
// Render: 0.016 | |
// Render: 0.032 | |
// Render: 0.048 | |
// ... | |
// Render: 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is an examination of implementing animations that require incremental state changes, on top for Flux + React. This exercise assumes that the animation is not suitable for implementation via CSS. The initial code above is an abstract animation loop, which is to serve as a reference point for mapping functionality into a Flux + React architecture.