Scroll-driven playback runtime for pre-rendered Manim animations.
npm install @mihirsarya/manim-scroll-runtimeCore scroll-driven playback runtime for pre-rendered Manim animations. Works in any JavaScript environment—use directly in vanilla JS or as the foundation for framework integrations.
``bash`
npm install @mihirsarya/manim-scroll-runtime
Or use the unified package (recommended for React/Next.js):
`bash`
npm install @mihirsarya/manim-scroll
- Video or frame-by-frame playback with automatic fallback
- Flexible scroll ranges via presets, relative units, or pixels
- Native text animation using SVG (no pre-rendered assets needed)
- Zero framework dependencies for the core runtime
`ts
import { registerScrollAnimation } from "@mihirsarya/manim-scroll-runtime";
const container = document.querySelector("#hero") as HTMLElement;
const cleanup = await registerScrollAnimation({
container,
manifestUrl: "/assets/scene/manifest.json",
scrollRange: "viewport",
onReady: () => console.log("Animation ready"),
onProgress: (progress) => console.log(Progress: ${progress}),
});
// Call cleanup() when done to remove listeners
`
`ts
import { registerNativeAnimation } from "@mihirsarya/manim-scroll-runtime";
const container = document.querySelector("#text") as HTMLElement;
const cleanup = await registerNativeAnimation({
container,
text: "Hello World",
fontSize: 48,
color: "#ffffff",
scrollRange: "viewport",
onReady: () => console.log("Ready"),
});
`
- registerScrollAnimation(options) - Register a scroll-driven animation with pre-rendered assets
- registerNativeAnimation(options) - Register a native SVG text animation
- NativeTextPlayer - Low-level native text animation player
- RenderManifest - Animation manifest schemaScrollAnimationOptions
- - Options for registerScrollAnimationNativeAnimationOptions
- - Options for registerNativeAnimationScrollRange
- , ScrollRangePreset, ScrollRangeValue - Scroll range types
Registers a scroll-driven animation using pre-rendered video or frame assets.
`ts`
interface ScrollAnimationOptions {
/* Container element for the animation /
container: HTMLElement;
/* URL to the animation manifest.json /
manifestUrl: string;
/* Playback mode (default: "auto") /
mode?: "auto" | "frames" | "video";
/* Optional canvas element (created automatically if not provided) /
canvas?: HTMLCanvasElement;
/* Scroll range configuration /
scrollRange?: ScrollRangeValue;
/* Called when animation is loaded and ready /
onReady?: () => void;
/* Called on scroll progress updates (0 to 1) /
onProgress?: (progress: number) => void;
}
Returns: Promise<() => void> - Cleanup function to remove listeners
Registers a native text animation that renders in the browser using SVG, replicating Manim's Write/DrawBorderThenFill effect.
`ts`
interface NativeAnimationOptions {
/* Container element for the animation /
container: HTMLElement;
/* Text to animate /
text: string;
/* Font size in pixels (inherits from parent if not specified) /
fontSize?: number;
/* Text color (hex or CSS color) /
color?: string;
/* URL to a font file (woff, woff2, ttf, otf) /
fontUrl?: string;
/* Stroke width for the drawing phase (default: 2) /
strokeWidth?: number;
/* Scroll range configuration /
scrollRange?: ScrollRangeValue;
/* Called when animation is loaded and ready /
onReady?: () => void;
/* Called on scroll progress updates (0 to 1) /
onProgress?: (progress: number) => void;
}
Returns: Promise<() => void> - Cleanup function to remove listeners
The scrollRange option controls when the animation plays relative to scroll position.
`ts
// Animation plays as element crosses the viewport (most common)
scrollRange: "viewport"
// Animation tied to element's own scroll position
scrollRange: "element"
// Animation spans entire document scroll
scrollRange: "full"
`
Use viewport height (vh) or element percentage (%):
`ts
// Start when element is 100vh from top, end at -50% of element height
scrollRange: ["100vh", "-50%"]
// Mix units as needed
scrollRange: ["80vh", "-100%"]
`
For precise control:
`ts
// As a tuple
scrollRange: [800, -400]
// As an object (legacy format)
scrollRange: { start: 800, end: -400 }
`
The manifest.json file describes a pre-rendered animation:
`ts`
interface RenderManifest {
/* Scene name /
scene: string;
/* Frames per second /
fps: number;
/* Canvas width /
width: number;
/* Canvas height /
height: number;
/* Array of frame image URLs /
frames: string[];
/* Video URL (null if not available) /
video: string | null;
/* Whether rendered with transparent background /
transparent?: boolean;
/* Whether this is an inline animation /
inline?: boolean;
/* Aspect ratio for inline sizing /
aspectRatio?: number | null;
}
| Mode | Description |
|------|-------------|
| "auto" | Uses video if available, falls back to frames |"video"
| | Forces video playback (fails if no video) |"frames"
| | Forces frame-by-frame playback |
`html``
- opentype.js - For native text animation font parsing
MIT