PathFollow
Animate elements along SVG paths with high-performance sampling
PathFollow animates elements along SVG paths with pre-baked sampling for optimal performance. Elements can auto-rotate to follow the path direction and be offset perpendicular to the path.
Overview
PathFollow uses PathResource internally for O(log n) path sampling, making it significantly faster than traditional motion path implementations. Key features:
- Progress-based animation - Animate from 0-1 along the path
- Auto-rotation - Elements rotate to follow path direction
- Perpendicular offsets - Position elements beside the path
- Manual control - Set progress directly for scroll/slider linking
Basic Usage
PathFollow.to()
Animate an element along a path.
import { PathFollow } from 'faster-motion';
PathFollow.to('#rocket', {
path: '#flight-path',
progress: 1, // Animate from 0 to 1
duration: 3000,
autoRotate: true
});Try it: Basic Path Following
PathFollow.to('#circle', {
path: '#curve-path',
progress: 1,
duration: 2000,
ease: 'easeInOut'
});Progress Range
Animate between specific progress values:
// Animate from 25% to 75% of path
PathFollow.to('#element', {
path: '#my-path',
progress: [0.25, 0.75],
duration: 2000
});Path Sources
PathFollow accepts paths in multiple formats:
SVG Path String
PathFollow.to('#element', {
path: 'M 0,100 C 100,0 200,200 300,100',
duration: 2000
});DOM Element or Selector
// CSS selector
PathFollow.to('#rocket', {
path: '#flight-path',
duration: 2000
});
// DOM element
const pathEl = document.querySelector('#my-path');
PathFollow.to('#rocket', {
path: pathEl,
duration: 2000
});PathResource Instance
For best performance when reusing paths:
import { PathResource, PathFollow } from 'faster-motion';
// Create once, reuse many times
const orbit = new PathResource({
path: '#orbit-path',
bakeInterval: 5
});
PathFollow.to('#planet1', { path: orbit, duration: 5000 });
PathFollow.to('#planet2', { path: orbit, duration: 8000 });
PathFollow.to('#planet3', { path: orbit, duration: 12000 });Auto-Rotation
autoRotate
When enabled (default), elements rotate to follow the path direction.
PathFollow.to('#arrow', {
path: '#curved-path',
autoRotate: true, // Default
duration: 2000
});Try it: Auto-Rotate
PathFollow.to('#rocket', {
path: '#flight-path',
progress: 1,
autoRotate: true,
rotationOffset: -90, // Point nose forward
duration: 3000,
ease: 'power2.inOut'
});rotationOffset
Add additional rotation after auto-rotate is applied.
PathFollow.to('#rocket', {
path: '#path',
autoRotate: true,
rotationOffset: -90, // Rotate 90° counter-clockwise
duration: 2000
});Common values:
0- Element's right side points forward-90- Element's top points forward (useful for arrows/rockets)90- Element's bottom points forward180- Element's left side points forward
Perpendicular Offsets
Position elements beside the path rather than on it.
offsetX (Along Tangent)
Offset in the direction of travel.
PathFollow.to('#element', {
path: '#path',
offsetX: 20, // 20px ahead of path position
duration: 2000
});offsetY (Perpendicular)
Offset perpendicular to the path direction.
PathFollow.to('#element', {
path: '#path',
offsetY: 30, // 30px to the left of path
duration: 2000
});
PathFollow.to('#element2', {
path: '#path',
offsetY: -30, // 30px to the right of path
duration: 2000
});Offset Visualization:
↑ offsetY (positive = left)
|
←----●----→ offsetX (positive = forward)
|
↓ offsetY (negative = right)
════════════► Path directionLooping
loop
Control behavior when progress goes beyond 0-1 range.
// Continuous orbit
PathFollow.to('#satellite', {
path: '#orbit',
progress: [0, 3], // Go around 3 times
loop: true, // Wrap around at ends
duration: 10000
});When loop: true:
- Progress 1.5 → position at 0.5
- Progress -0.25 → position at 0.75
When loop: false (default for non-closed paths):
- Progress clamps to 0-1 range
Animation Options
| Option | Type | Default | Description |
|---|---|---|---|
path | PathResource | string | Element | Required | Path to follow |
progress | number | [start, end] | 1 | Target progress (0-1) |
progressRatio | number | - | Alias for progress |
autoRotate | boolean | true | Rotate with path direction |
rotationOffset | number | 0 | Additional rotation (degrees) |
loop | boolean | true | Wrap at path boundaries |
offsetX | number | 0 | Tangent offset (pixels) |
offsetY | number | 0 | Perpendicular offset (pixels) |
duration | number | 1000 | Animation duration (ms) |
ease | string | 'power2.inOut' | Easing function |
delay | number | 0 | Start delay (ms) |
repeat | number | 0 | Repeat count (-1 = infinite) |
yoyo | boolean | false | Reverse on repeat |
onUpdate | (progress, sample) => void | - | Called each frame |
onComplete | () => void | - | Called when complete |
Getting Path Points
Query path positions without animating an element:
const point = PathFollow.getPointAt('#path', 0.5);
console.log(point.x, point.y); // Position
console.log(point.angle); // Tangent angle (radians)
console.log(point.tangentX); // Normalized tangent X
console.log(point.tangentY); // Normalized tangent YOrbit Animation Example
Try it: Planetary Orbit
const orbit = new PathResource({
path: '#orbit-ellipse',
closed: true
});
// Multiple planets at different speeds
PathFollow.to('#mercury', {
path: orbit,
progress: [0, 1],
duration: 2000,
repeat: -1,
ease: 'linear'
});
PathFollow.to('#earth', {
path: orbit,
progress: [0.33, 1.33], // Start offset
duration: 5000,
repeat: -1,
ease: 'linear'
});Shorthand Function
import { pathFollow } from 'faster-motion';
// Shorthand for PathFollow.to()
pathFollow('#element', {
path: '#my-path',
duration: 2000
});TypeScript Support
import { PathFollow, PathFollowOptions, SampleResult, PathResource } from 'faster-motion';
const options: PathFollowOptions = {
path: '#flight-path',
progress: 1,
autoRotate: true,
rotationOffset: -90,
duration: 3000,
onUpdate: (progress: number, sample: SampleResult) => {
console.log(`At ${progress * 100}%: (${sample.x}, ${sample.y})`);
}
};
PathFollow.to('#rocket', options);See Also
- PathFollow Advanced - Manual control, stagger, distribute
- PathResource - Reusable path data
- TrimPath - Animate path stroke visibility