这是什么
DynMath 让你用几乎原版的 Manim Python 代码编写数学动画,并在动画里加入方便演示和讲解的交互控件(滑块、开关、可编辑数字 / 矩阵 / 表格)。
和以往的做法(先离线渲染成视频,或在浏览器中运行完整 Python 环境)不同,这里的动画通过轻量级库直接在浏览器里即时渲染:改完代码点一下运行,马上就能看到修改后的结果, 体积和性能相比于传统方案都有显著提升。可以直接到游乐场里体验。
代码与原版 Manim 的写法基本一致,numpy 也几乎支持。 暂不支持完整的 3D 渲染、文件读写,以及除 manim / numpy 之外的标准库 import。
快捷键与操作
| 运行 | ⌘/Ctrl + Enter(编辑器 / 游乐场内),或点「运行」按钮 |
|---|---|
| 保存 | ⌘/Ctrl + S(游乐场里是打开「发布到我的课件」弹窗) |
| 下一步 | 空格:交互场景在 blueprint 与 construct 之间推进 |
| 重来 | r:交互场景回到从头;展示页里非交互场景播放结束后会自动从头重播 |
| 操作控件 | 拖动滑块、点击开关、点击数字后直接输入(Enter 提交,Esc 取消) |
在输入文字 / 编辑数字时,播放类快捷键不会触发,避免冲突。
制作流程:「我的课件」点「+ 新建课件」,在左侧列表里新建 / 改名 / 排序 / 删除每一页;右侧写代码、运行、保存。在「设置」里选择可见性(未发布 / 私有发布,凭链接访问 / 发布到主页)并设置访问地址 /p/xxx。 展示页无需登录即可打开;别人点「我也想做这个动画」会进入游乐场,改完可发布到自己的课件。
交互控件
把 Scene 换成 InteractiveScene,并在 blueprint() 里创建控件。控件本身就是普通的 mobject,可以 self.add(...)、参与动画、被读取。要在 construct() 里用到的对象,记得在 blueprint() 里存到 self 上(如 self.circle = circle)。
- blueprint():动画播放前的静置阶段,每一帧都会重跑所有
add_reaction回调。适合放控件和「随控件实时变化」的图形。 - construct():点「下一步」后进入。这里
add_reaction不再生效,改用普通的add_updater。 - 两个方法都可以留空其一。想「只有交互、没有后续动画」,就只写
blueprint。
目前一共有 7 种控件:Slider、PathSlider、Switch、InputDecimalNumber、InputInteger、InputDecimalMatrix、 InputDecimalTable。它们都是 mobject,用 get_value() 读值。
多阶段:set_storyboard
默认情况下,一个 InteractiveScene 只有一组 blueprint / construct。如果需要「交互 → 讲解 → 再交互 → 再讲解」的多段流程,就在 setup() 里用 self.set_storyboard(...) 规划整个流程。
- 每个元素是一个
(blueprint, construct)二元组;某一半填None表示跳过该阶段(例如只要交互、不要动画)。 - 按「下一步」(空格)依次推进:一个阶段的
blueprint结束后进入它的construct,再进入下一组的blueprint。 - 调用之后
blueprint()/construct()不再被隐式执行,只按表里的顺序走;set_script是它的别名。 - 控件只在
blueprint阶段可拖动 / 点击,construct播放动画期间指针事件被忽略。
Slider(滑块)
一条轨道 + 一个圆点。拖动时 get_value() 返回 value_range 区间内的浮点数(左闭右闭)。
| 参数 | 默认 | 说明 |
|---|---|---|
start / end | [-1,0,0] / [1,0,0] | 轨道两端(世界坐标,可用 axes.c2p) |
value_range | (0, 1) | 值域闭区间 |
init_value | value_range[0] | 初始值 |
color / stroke_width | YELLOW / 6 | 颜色与轨道线宽 |
track_opacity / knob_opacity | 1 / 1 | 轨道 / 滑块透明度,设 0 即隐藏 |
想让「真正的滑块」是别的图形(如三角形),用 slider.attach(mobj): 圆点会自动变透明,被附着的物体随 set_value 一起移动;slider.unattach() 解除。命中判定始终基于轨道线段,与透明度无关。
PathSlider(曲线滑块)
轨道可以是任意 VMobject(曲线、折线、VGroup 拼出的路径)。 其余行为与 Slider 相同:value_range 左端对应路径起点、 右端对应终点,按弧长比例映射;拖动只沿路径切线方向移动,不会跳到路径外。
| 参数 | 默认 | 说明 |
|---|---|---|
path(位置参数) | 必填 | 轨道 VMobject,会被直接采用并上色 |
is_closed | False | 路径是否首尾相接;为真时值按 value_range 长度循环 |
| 其余参数 | 同 Slider | value_range / init_value / color / stroke_width / track_opacity / knob_opacity / knob_radius / hit_radius |
is_closed=True 时(如 Circle),set_value 对超出区间的值按区间长度取模,拖动越过接缝会从一端绕回另一端。attach / unattach 用法与 Slider 相同。
Switch(开关)
蓝白配色开关,点击切换布尔值。get_value() 返回 True / False。
| 参数 | 默认 | 说明 |
|---|---|---|
value | False | 初始状态(也可作为第一个位置参数) |
width / height | 0.66 / 0.33 | 尺寸 |
color | BLUE_E | 打开时的蓝色 |
set_value(False) 直接设置,toggle() 取反。
InputDecimalNumber(可编辑数字)
继承自 DecimalNumber,但可以点击并在原地输入,数字上方会出现 ^ 光标。get_value() 返回当前数值。
只接受数字、.、-;按 Enter 或点击别处提交,Esc 取消。参数与 DecimalNumber 相同,其中 group_with_commas 默认关闭。注意 num_decimal_places 会重新格式化数值,固定小数位或整数场景使用最自然。
InputInteger(可编辑整数)
用法与 InputDecimalNumber 相同,但小数位数固定为 0, 编辑时不接受小数点,get_value() 返回整数(四舍五入后截断)。
InputDecimalMatrix(可编辑矩阵)
与 DecimalMatrix 参数完全一致,区别是每个格子都是 InputDecimalNumber,可以单独点击编辑;编辑后矩阵自动重排 (列宽按各列最宽的格子、行高按各行最高的格子),括号跟着内容伸缩,中心保持不变。
A.get_entries()/A.mob_matrix[i][j]返回格子, 可get_value()/set_value(v)。- 格子的小数位等参数通过
element_to_mobject_config={"num_decimal_places": 1}传入。 - 编辑任一格会触发
A.relayout();也可手动调用。
InputDecimalTable(可编辑表格)
与 DecimalTable 参数完全一致,区别是每个数据格都是 InputDecimalNumber,编辑后自动重排并用新的行列位置重建表格线 (include_outer_lines 等行为不变),中心保持不变。
T.get_entries(pos)/T.get_entries_without_labels(pos)读取表格内容,用法与Table一致。- 编辑触发
T.relayout(),会重建T.horizontal_lines/T.vertical_lines。
示例
点每一段下面的「亲自试一试」,会在游乐场里打开并自动运行;改一改数字再运行即可。