Helios provides a comprehensive set of animation helpers to create smooth, natural motion in your video compositions. These utilities handle interpolation, spring physics, and easing functions.
interpolate()
Maps an input value from one range to another with support for easing and extrapolation.
import { interpolate } from '@helios-project/core' ;
const opacity = interpolate ( frame , [ 0 , 30 ], [ 0 , 1 ]);
const scale = interpolate ( frame , [ 0 , 60 , 120 ], [ 1 , 1.5 , 1 ]);
Parameters
Array of input values (must be strictly monotonically increasing). Minimum 2 elements.
Array of output values (must match length of inputRange)
Configuration for extrapolation and easing Behavior when input is less than the minimum inputRange value:
extend: Continue the trend linearly
clamp: Return the first outputRange value
identity: Return the input value unchanged
Behavior when input is greater than the maximum inputRange value
Easing function to apply to the interpolation. Use functions from the Easing object.
Returns
number - The interpolated value
Examples
Basic interpolation
import { interpolate } from '@helios-project/core' ;
import { useVideoFrame } from './hooks/useVideoFrame' ;
function AnimatedBox ({ helios }) {
const frame = useVideoFrame ( helios );
// Fade in over first 30 frames
const opacity = interpolate ( frame , [ 0 , 30 ], [ 0 , 1 ]);
// Move from left to right
const x = interpolate ( frame , [ 0 , 120 ], [ 0 , 800 ]);
return (
< div style = {{ opacity , transform : `translateX( ${ x } px)` }} >
Content
</ div >
);
}
Multi-point interpolation
// Create a bounce effect with multiple keyframes
const y = interpolate (
frame ,
[ 0 , 30 , 60 , 90 , 120 ],
[ 0 , - 100 , - 50 , - 75 , 0 ]
);
const x = interpolate (
frame ,
[ 0 , 60 ],
[ 0 , 200 ],
{ extrapolateRight: 'clamp' } // Stop at 200 after frame 60
);
With easing
import { interpolate , Easing } from '@helios-project/core' ;
const scale = interpolate (
frame ,
[ 0 , 60 ],
[ 1 , 2 ],
{ easing: Easing . cubic . out }
);
spring()
Calculates spring physics values for natural, bouncy motion using a damped harmonic oscillator simulation.
import { spring } from '@helios-project/core' ;
const scale = spring ({
frame ,
fps: 30 ,
from: 0 ,
to: 1 ,
config: { stiffness: 100 , damping: 10 }
});
Parameters
Spring configuration object Frames per second of the composition
Starting value of the spring animation
Target value the spring animates toward
Spring physics parameters Mass of the spring. Higher values create slower, heavier motion.
Spring stiffness. Higher values create faster, tighter springs.
Damping force. Higher values reduce oscillation and settling time.
If true, prevents the spring from overshooting the target value
Optional duration hint (currently ignored as physics simulations are time-based)
Returns
number - The calculated spring value at the current frame
Examples
Basic spring animation
import { spring } from '@helios-project/core' ;
function SpringBox ({ helios }) {
const frame = useVideoFrame ( helios );
const scale = spring ({
frame ,
fps: 30 ,
from: 0 ,
to: 1
});
return (
< div style = {{ transform : `scale( ${ scale } )` }} >
Bouncy !
</ div >
);
}
Configuring spring physics
// Tight, fast spring
const tightSpring = spring ({
frame ,
fps: 30 ,
config: { stiffness: 200 , damping: 15 }
});
// Loose, wobbly spring
const wobblySpring = spring ({
frame ,
fps: 30 ,
config: { stiffness: 50 , damping: 5 }
});
// Heavy, slow spring
const heavySpring = spring ({
frame ,
fps: 30 ,
config: { mass: 5 , stiffness: 100 , damping: 20 }
});
Preventing overshoot
const scale = spring ({
frame ,
fps: 30 ,
from: 0 ,
to: 1 ,
config: { overshootClamping: true } // Never goes above 1
});
calculateSpringDuration()
Estimates how many frames a spring animation needs to settle within a threshold.
import { calculateSpringDuration } from '@helios-project/core' ;
const duration = calculateSpringDuration (
{ fps: 30 , config: { stiffness: 100 , damping: 10 } },
0.001 // threshold
);
Parameters
options
Omit<SpringOptions, 'frame'>
required
Spring configuration (same as spring() but without frame)
Distance from target value to consider the spring “settled”
Returns
number - Estimated duration in frames
Easing functions
Helios includes a comprehensive library of easing functions for use with interpolate() and other animations.
import { Easing } from '@helios-project/core' ;
Available easing functions
Basic
Easing.linear - No easing, linear interpolation
Easing.step(steps) - Step function with specified number of steps
Easing.bezier(x1, y1, x2, y2) - Custom cubic bezier curve
Polynomial
All polynomial easings have .in, .out, and .inOut variants:
Easing.quad - Quadratic (t²)
Easing.cubic - Cubic (t³)
Easing.quart - Quartic (t⁴)
Easing.quint - Quintic (t⁵)
Transcendental
Easing.sine - Sinusoidal easing
Easing.expo - Exponential easing
Easing.circ - Circular easing
Physical
Easing.back - Overshoots then returns
Easing.elastic - Elastic bounce effect
Easing.bounce - Bouncing ball effect
Examples
import { interpolate , Easing } from '@helios-project/core' ;
// Ease in (slow start)
const x1 = interpolate ( frame , [ 0 , 60 ], [ 0 , 100 ], {
easing: Easing . cubic . in
});
// Ease out (slow end)
const x2 = interpolate ( frame , [ 0 , 60 ], [ 0 , 100 ], {
easing: Easing . cubic . out
});
// Ease in-out (slow start and end)
const x3 = interpolate ( frame , [ 0 , 60 ], [ 0 , 100 ], {
easing: Easing . cubic . inOut
});
// Elastic bounce
const scale = interpolate ( frame , [ 0 , 60 ], [ 0 , 1 ], {
easing: Easing . elastic . out
});
// Custom bezier
const custom = interpolate ( frame , [ 0 , 60 ], [ 0 , 1 ], {
easing: Easing . bezier ( 0.68 , - 0.55 , 0.265 , 1.55 )
});
// Step animation (5 steps)
const stepped = interpolate ( frame , [ 0 , 60 ], [ 0 , 100 ], {
easing: Easing . step ( 5 )
});
Common patterns
Typewriter effect
import { interpolate } from '@helios-project/core' ;
function Typewriter ({ text , frame , start , end }) {
const visibleCount = Math . floor (
interpolate ( frame , [ start , end ], [ 0 , text . length ])
);
return < div >{text.slice( 0 , visibleCount)} </ div > ;
}
Stagger animations
function StaggeredList ({ items , frame }) {
return items . map (( item , i ) => {
const delay = i * 10 ; // 10 frames between each
const opacity = interpolate (
frame ,
[ delay , delay + 20 ],
[ 0 , 1 ],
{ extrapolateRight: 'clamp' }
);
return (
< div key = { i } style = {{ opacity }} >
{ item }
</ div >
);
});
}
Combining helpers
function AnimatedElement ({ frame }) {
// Use interpolate for position
const x = interpolate ( frame , [ 0 , 60 ], [ 0 , 200 ]);
// Use spring for scale
const scale = spring ({ frame , fps: 30 , from: 0 , to: 1 });
// Use easing for rotation
const rotation = interpolate (
frame ,
[ 0 , 120 ],
[ 0 , 360 ],
{ easing: Easing . cubic . inOut }
);
return (
< div style = {{
transform : `translateX( ${ x } px) scale( ${ scale } ) rotate( ${ rotation } deg)`
}} >
Content
</ div >
);
}