Getting Started
StudioMotion is a zero-dependency ~2.8 kB micro-engine. Install via NPM or load directly in vanilla HTML.
# Install via NPM
npm install studiomotion
// Import in your project
import { animate } from 'studiomotion';
animate({
targets: '#demoTarget1',
scale: [0.8, 1],
rotate: [-10, 0],
duration: 650,
easing: 'spring'
});
Timer
High-precision micro-scheduler with delta step isolation and custom tick listener loops.
import { timer } from 'studiomotion';
const myTimer = timer({
duration: 10000,
loop: true,
onTick: (elapsedMs) => {
document.getElementById('timerDisplay').innerText = (elapsedMs / 1000).toFixed(2) + 's';
}
});
myTimer.start();
Animation
Hardware-accelerated 3D spatial transforms (rotateX, rotateY, translateZ) and harmonic springs.
StudioMotion.animate({
targets: '#demoTarget3',
rotateX: [40, 0],
rotateY: [-35, 0],
scale: [0.85, 1],
duration: 800,
easing: 'spring'
});
Animation Subtypes & Value Formats
StudioMotion supports all 9 native animation target subtypes and value modifiers:
Hardware-accelerated subpixel GPU matrices.
animate({
targets: '.card',
translateX: [-50, 0],
rotateX: [45, 0],
scale: [0.8, 1]
});
Reactive custom properties for shaders and glow effects.
animate({
targets: '.glow-box',
'--glow-size': ['5px', '40px'],
'--glow-alpha': [0.2, 0.9]
});
Vector radius, centers, coordinates, and dash offsets.
animate({
targets: '#vectorCircle',
r: [10, 45],
strokeDashoffset: [200, 0]
});
Animate numerical properties, scores, and canvas cameras.
const state = { score: 0 };
animate({
targets: state,
score: [0, 9500],
round: 1
});
Calculate relative steps from current element values.
animate({
targets: '.stepper',
translateX: '+=150px',
rotate: '*=2'
});
Multi-step keyframe sequences within a single tween.
animate({
targets: '.box',
keyframes: [
{ translateY: -30, scale: 1.1 },
{ translateX: 40, rotate: 10 },
{ translateY: 0, translateX: 0, scale: 1 }
]
});
Timeline
Sequential choreography with relative offsets ('+=100', '-=200') and
playback controls.
const tl = StudioMotion.timeline();
tl.add({ targets: '#tlNode1', translateY: [-30, 0], scale: [0.8, 1], duration: 400, easing: 'spring' })
.add({ targets: '#tlNode2', translateY: [-30, 0], scale: [0.8, 1], duration: 400, easing: 'spring' }, '-=200')
.add({ targets: '#tlNode3', translateY: [-30, 0], scale: [0.8, 1], duration: 400, easing: 'spring' }, '-=200');
Animatable
Reactive state proxy that animates DOM elements automatically on property mutations.
const state = StudioMotion.animatable({ scale: 1, y: 0 });
// Mutating state triggers automatic physics tween
state.scale = 1.25;
state.y = 20;
Draggable
Momentum pointer dragging with friction decay and boundary constraints.
StudioMotion.draggable('#dragTarget', {
momentum: true,
friction: 0.92,
bounds: '#dragBoundary'
});
Scope
Automatic memory garbage collection and animation unmount cleanup.
const ctx = StudioMotion.scope(container);
ctx.add(StudioMotion.animate({ targets: '#scopeTarget', rotate: [0, 180], duration: 600 }));
// Clean up completely when component unmounts
ctx.revert();
Scroll
Viewport scrubbing and scroll-driven 3D transforms without third-party plugins.
StudioMotion.onScroll({
target: '#scrollTarget',
sync: true, // Progressively scrub
animation: {
rotateX: [40, 0],
scale: [0.8, 1],
opacity: [0.3, 1]
}
});
SVG (Morph & Draw)
Vector line drawing (createDrawable) and path coordinate morphing
(morphTo).
StudioMotion.draw('#svgDrawPath', {
duration: 900,
easing: 'easeInOutCubic'
});
Utils
2D matrix grid stagger calculations, clamp, lerp, and color parsers.
StudioMotion.animate({
targets: '.m-cell',
scale: [0.2, 1],
stagger: StudioMotion.stagger(40, { from: 'center' }),
duration: 600,
easing: 'spring'
});
Easing Visualizer & Studio
Interactive 3-column curve studio with real-time spring dynamics, bezier handles, 4-quadrant preview, and instant StudioMotion JavaScript & CSS code generation.
WAAPI & Adapters
Direct browser compositor offload and Three.js 3D WebGL object animations.
// Offloaded directly to browser compositor thread
StudioMotion.waapi('#waapiTarget', [
{ transform: 'translateY(40px) scale(0.9)', opacity: 0 },
{ transform: 'translateY(0px) scale(1)', opacity: 1 }
], { duration: 600 });