@mihirsarya/manim-scroll-react
v0.2.2
Published
React wrapper for scroll-driven Manim animations.
Readme
@mihirsarya/manim-scroll-react
React components and hooks for scroll-driven Manim animations.
Installation
npm install @mihirsarya/manim-scroll-reactOr use the unified package (recommended):
npm install @mihirsarya/manim-scrollRequirements
- React 18+
@mihirsarya/manim-scroll-runtime(peer dependency, installed automatically)
Quick Start
With Next.js Plugin (Recommended)
When using with @mihirsarya/manim-scroll-next, animations are automatically resolved:
import { ManimScroll } from "@mihirsarya/manim-scroll-react";
export default function Page() {
return (
<ManimScroll
scene="TextScene"
fontSize={72}
color="#ffffff"
scrollRange="viewport"
>
Welcome to my site
</ManimScroll>
);
}Manual Mode
Without the Next.js plugin, provide an explicit manifest URL:
import { ManimScroll } from "@mihirsarya/manim-scroll-react";
export default function Page() {
return (
<ManimScroll
manifestUrl="/assets/scene/manifest.json"
scrollRange="viewport"
>
Scroll-driven text
</ManimScroll>
);
}Native Mode
For text animations without pre-rendered assets:
<ManimScroll mode="native" fontSize={48} color="#ffffff">
Animate this text
</ManimScroll>Exports
Components
ManimScroll- Scroll-driven animation component
Hooks
useManimScroll- Hook for custom integrations with pre-rendered assetsuseNativeAnimation- Hook for native SVG text animation
Utilities
computePropsHash- Compute hash for animation propsextractChildrenText- Extract text from React children
Types
ManimScrollProps,ManimAnimationPropsUseManimScrollOptions,UseManimScrollResultUseNativeAnimationOptions,UseNativeAnimationResult
ManimScroll Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| scene | string | "TextScene" | Manim scene name |
| fontSize | number | - | Font size for text animations |
| color | string | - | Color as hex string |
| font | string | - | Font family |
| inline | boolean | false | Enable inline mode |
| padding | number | 0.2 | Padding in inline mode (Manim units) |
| mode | "auto" \| "video" \| "frames" \| "native" | "auto" | Playback mode |
| scrollRange | ScrollRangeValue | "viewport" | Scroll range configuration |
| manifestUrl | string | - | Explicit manifest URL |
| fontUrl | string | - | Font file URL for native mode |
| strokeWidth | number | 2 | Stroke width for native mode |
| onReady | () => void | - | Called when animation is loaded |
| onProgress | (progress: number) => void | - | Called on scroll progress |
| canvas | { width?, height? } | - | Canvas dimensions |
| className | string | - | CSS class |
| style | CSSProperties | - | Inline styles |
| children | ReactNode | - | Text content |
useManimScroll Hook
For advanced use cases requiring custom control:
import { useRef } from "react";
import { useManimScroll } from "@mihirsarya/manim-scroll-react";
function CustomAnimation() {
const containerRef = useRef<HTMLDivElement>(null);
const { progress, isReady, error, pause, resume, seek } = useManimScroll({
ref: containerRef,
manifestUrl: "/assets/scene/manifest.json",
scrollRange: "viewport",
});
return (
<div ref={containerRef} style={{ height: "100vh" }}>
{!isReady && <div>Loading...</div>}
{error && <div>Error: {error.message}</div>}
<div>Progress: {Math.round(progress * 100)}%</div>
<button onClick={pause}>Pause</button>
<button onClick={resume}>Resume</button>
</div>
);
}Hook Options
| Option | Type | Description |
|--------|------|-------------|
| ref | RefObject<HTMLElement> | Container element ref (required) |
| manifestUrl | string | Explicit manifest URL |
| scene | string | Scene name for auto-resolution |
| animationProps | Record<string, unknown> | Props for auto-resolution |
| mode | "auto" \| "frames" \| "video" | Playback mode |
| scrollRange | ScrollRangeValue | Scroll range configuration |
| canvasDimensions | { width?, height? } | Canvas size |
| enabled | boolean | Whether the hook is active |
Hook Return Value
| Property | Type | Description |
|----------|------|-------------|
| progress | number | Current scroll progress (0 to 1) |
| isReady | boolean | Whether animation is loaded |
| error | Error \| null | Loading error, if any |
| canvasRef | RefObject<HTMLCanvasElement> | Canvas element ref |
| seek | (progress: number) => void | Seek to specific progress |
| pause | () => void | Pause scroll-driven updates |
| resume | () => void | Resume scroll-driven updates |
| isPaused | boolean | Whether updates are paused |
useNativeAnimation Hook
For native SVG text animation without pre-rendered assets:
import { useRef } from "react";
import { useNativeAnimation } from "@mihirsarya/manim-scroll-react";
function NativeTextAnimation() {
const containerRef = useRef<HTMLDivElement>(null);
const { progress, isReady } = useNativeAnimation({
ref: containerRef,
text: "Hello World",
fontSize: 48,
color: "#ffffff",
});
return (
<div ref={containerRef} style={{ height: "100vh" }}>
{!isReady && <div>Loading...</div>}
</div>
);
}Hook Options
| Option | Type | Description |
|--------|------|-------------|
| ref | RefObject<HTMLElement> | Container element ref (required) |
| text | string | Text to animate (required) |
| fontSize | number | Font size in pixels (inherits from parent if not set) |
| color | string | Text color |
| fontUrl | string | URL to font file for opentype.js |
| strokeWidth | number | Stroke width for drawing phase |
| scrollRange | ScrollRangeValue | Scroll range configuration |
| enabled | boolean | Whether the hook is active |
Scroll Range Configuration
// Presets
scrollRange="viewport" // Animation plays as element crosses viewport
scrollRange="element" // Tied to element's own scroll position
scrollRange="full" // Spans entire document scroll
// Relative units
scrollRange={["100vh", "-50%"]}
// Pixel values
scrollRange={[800, -400]}
scrollRange={{ start: 800, end: -400 }}License
MIT
