Hotdry.
web

Manim 动画引擎 TypeScript 移植:浏览器原生 Canvas/WebGL 数学可视化

基于 manim-web 项目,实现 3Blue1Brown 风格数学动画在浏览器无 Python 依赖运行,提供安装、API 用法与性能优化参数。

Manim 是 3Blue1Brown 使用的著名数学动画库,以其精确的几何变换、LaTeX 渲染和流畅动画闻名,但依赖 Python 环境、FFmpeg 渲染视频,导致部署门槛高、实时交互难。manim-web 将其核心移植到 TypeScript,完全浏览器原生执行,利用 Canvas 2D/WebGL(Three.js 3D 支持)和 KaTeX 实现零依赖可视化。这不仅保留了原 API 相似性,还支持交互式场景,适用于 Web 教育工具、数据可视化仪表盘。

项目核心技术栈与实现原理

manim-web 的渲染层基于 WebGL,利用 Three.js 处理 3D 几何(如 Sphere、Surface3D)和光照(AmbientLight、DirectionalLight),2D 则 fallback 到 Canvas2D 以兼容低端设备。LaTeX 通过 KaTeX 即时渲染为 SVG 路径,支持 Create(描边绘制)、Transform(变形)等动画。动画系统采用时间线驱动:每个 Animation(如 FadeIn、MoveToTarget)定义 run 时长(默认 1s)、rateFunc(easing,如 linear、smooth)和 lagRatio(组动画延迟)。

关键创新是 Updater 机制:对象可附加动态回调,每帧(~60fps)更新位置 / 样式,实现 ValueTracker 驱动的实时曲线(如正弦波点追踪)。例如,ValueTracker.animateTo (target, duration=2) 平滑插值,支持 addUpdater ((mobj, dt) => mobj.rotate (dt)) 连续旋转。布尔运算(Union、Intersection)使用 ClipperLib 路径裁剪,3D 表面通过 ParametricFunction 生成顶点网格。

性能瓶颈主要在高分辨率 LaTeX(fontSize>48)和复杂网格(uResolution>50)。建议参数:strokeWidth=2-4(平衡清晰 / 渲染速)、fillOpacity=0.5(减少 overdraw)、numSamples=200(曲线采样)。浏览器 FPS 监控:requestAnimationFrame 内检查 deltaTime >16ms 时降级 resolution。

快速上手与基本参数配置

安装:npm i manim-web,导入 Scene/Circle 等。核心流程:

  1. 创建容器:<div id="container" style="width:800px;height:450px;"></div>
  2. 初始化 Scene:new Scene(container, {width:800, height:450, backgroundColor:'#000'})
  3. 构建对象:const circle = new Circle({radius:1.5, color:'blue', fillOpacity:0.8});
  4. 动画序列:await scene.play(new Create(circle, {duration:1.5}), new Transform(circle, square));
  5. 渲染循环:Scene 自动管理 RAF。

示例:正方形变圆(经典 demo):

import { Scene, Circle, Square, Create, Transform, FadeOut } from 'manim-web';

async function demo(scene: Scene) {
  const square = new Square({ sideLength: 3, color: 'blue' });
  const circle = new Circle({ radius: 1.5, color: 'green' });
  await scene.play(new Create(square, { rateFunc: 'ease-in-out', duration: 1 }));
  await scene.play(new Transform(square, circle, { pathArc: Math.PI/4 }));  // 弧形路径,参数可调
  await scene.play(new FadeOut(circle));
}
const scene = new Scene(document.getElementById('container'));
demo(scene);

参数清单:

  • Animation:duration=1(s),rateFunc='linear'/'cubic'/'ease',scaleFactor=1.2(缩放)。
  • Mobject:strokeWidth=3,strokeOpacity=0.9,fillColor='hsl (200,50%,50%)'(动态色)。
  • Axes/Graph:xRange=[-10,10,1](范围 / 刻度),plot (lambda x: sin (x), {color:'red', numSamples:300})。
  • 3D:ThreeDScene (phi=75° 仰角,theta=-45° 方位,fov=30, distance=20),Surface3D (uResolution=24)。

回滚策略:复杂场景 FPS<30 时,切换 MathTexSVG(矢量路径优于栅格)、禁用 shadows(light intensity=1.0)。

高级用法:交互与框架集成

支持 Draggable/Hoverable:mobj.setDraggable() 绑定 pointermove,实现交互函数图。ValueTracker + Updater 示例(动态角度):

const tracker = new ValueTracker(0);
const line = new Line(LEFT, RIGHT);
line.addUpdater(mob => mob.rotate(tracker.value * Math.PI/180));
await scene.play(tracker.animateTo(360, {duration:4}));  // 实时更新

框架集成:

  • React<ManimScene construct={demo} width={800} height={450} />
  • Vue<ManimScene :construct="demo" :width="800" />
  • Python 迁移:node tools/py2ts.cjs input.py -o output.ts 半自动转换。

3D 案例:高斯表面 Surface3D(func=(u,v)=>[u, exp(-(u^2+v^2)), -v], checkerboardColors=['orange','blue']),结合 beginAmbientCameraRotation (0.1) 自动旋转。

监控要点:

  • FPS:console.time ('frame'),阈值 < 45 降 uResolution=16。
  • 内存:复杂网格 < 1M verts,避免 VMobject 无限 appendPoints。
  • 兼容:Safari 降 WebGL2 to 1,polyfill KaTeX。

实际落地清单:

  1. 教育 demo:Sin/Cos 联动的单位圆 + 曲线(Axes.plot + Updater 线连接)。
  2. 数据图:BarChart + LaggedStart 逐条入场。
  3. 交互工具:ArgMin 优化可视化(dot 沿曲线滑至极值)。
  4. 导出:内置 GIF/Video(需 FFmpeg.js wasm,浏览器限 10s)。

此移植极大降低门槛,Web 开发者可即时原型数学内容,结合 WebAssembly 未来可进一步加速路径计算。

资料来源: [1] https://github.com/maloyan/manim-web (官方 Repo,包含 README 示例) [2] https://maloyan.github.io/manim-web/examples (在线 Demo)

查看归档