【Cursor实战】Cursor+Manim生成演示动画

564 阅读6分钟

前言

小伙伴们大家好,我是小溪,见字如面。如果你热衷教学演示但又苦于各种技术限制不知道如何制作一个直观的演示动画,那么今天即将登场的主角将会成为你的一生挚爱,它就是为了制作高质量的数学科普视频而设计的Manim。

对以往实战案例感兴趣的小伙伴也可以看往期:

关于Manim

Manim简介

Manim是一个用于创建数学动画的Python库。它由3Blue1Brown(格兰特·桑德森)开发,最初是为了制作高质量的数学科普视频而设计的。这些视频能够以直观且吸引人的方式展示复杂的数学概念,例如线性代数中的向量变换、微积分中的极限概念等。

它的出现填补了数学教育领域中动态可视化工具的空白。在传统的数学教学中,静态的图像和文字往往难以充分展示数学概念的动态演变过程,而Manim使得教师、教育工作者和数学爱好者能够轻松地将抽象的数学知识转化为生动的动画。

官网

官网地址:www.manim.community

图片

文档地址:docs.manim.community/en/stable/

图片

在线体验地址:hub.2i2c.mybinder.org/user/manimc…

图片

前期准备

创建Python项目

UV是一个Python项目管理库,感兴趣的小伙伴可以先行了解

UV官网文档:docs.astral.sh/uv/

# 初始化项目
$ uv init manim-examples
# 进入到项目
$ cd manim-examples
# 创建虚拟环境并激活
$ uv venv && source .venv/bin/activate

安装manim

环境安装有问题可以参考最下方常见问题

# 安装
$ uv add manim

在项目根目录创建一个src目录,最终得到如下项目结构

图片

Cursor添加Manim文档

图片

添加完成等待文档状态变为绿色即为解析成功

图片

安装Manim Sideview插件

Manim Sideview是一款Manim预览插件,无需手动执行指令运行即可查看Manim动画效果

图片

官方示例

先拿几个官方示例看一下Manim的基本使用方式和示例效果

绘制圆形动画

from manim import *
class CreateCircle(Scene):
    def construct(self):
        circle = Circle()
        circle.set_fill(PINK, opacity=0.5)
        self.play(Create(circle))

在命令行终端执行指令

$ manim -pql create_circle.py CreateCircle

Manim指令参数解析:

  • -p标志告诉 manim 在渲染场景后播放场景
  • -ql标志告诉 manim 以低质量(854x480 15FPS)渲染场景
  • -qm标志告诉 manim 以中等质量(1280x720 30FPS)渲染场景
  • -qh标志告诉 manim 以高质量(1920x1080 60FPS)渲染场景
  • -qp标志告诉 manim 以2k质量(2560x1440 60FPS)渲染场景
  • -qk标志告诉 manim 以4k质量(3840x2160 60FPS)渲染场景

执行完成后,会在指令执行路径下创建media目录并输出视频动画文件

图片

如果你觉得执行指令运行太过麻烦,也可以使用上面安装的 Manim Sideview插件 查看效果,打开Manim脚本文件,点击右上角的Manim Sideview预览按钮

图片

预览执行完成后会在Manim脚本右侧展示预览效果

图片

最终绘制的效果如下

图片

默认情况下,manim 将输出 .mp4 文件,如果希望动画输出 .gif 格式,可以使用 --format gif 标志。

$ manim -pql create_circle.py CreateCircle --format gif

正方形变换为圆形

from manim import *
class SquareToCircle(Scene):
    def construct(self):
        # 创建一个正方形
        square = Square()
        square.rotate(PI / 4)
        # 创建一个圆形
        circle = Circle()
        circle.set_fill(PINK, opacity=0.5)
        # 创建一个动画,将正方形变成圆形
        self.play(Create(square))
        self.play(Transform(square, circle))
        # 创建一个动画,淡出圆形
        self.play(FadeOut(circle))        

预览后效果如下:

图片

也可以**.animate** 语法制作动画

classAnimatedSquareToCircle(Scene):
defconstruct(self):
# 创建一个正方形
        square = Square()
# 创建一个圆形
        circle = Circle()
# 创建一个动画,将正方形变成圆形
self.play(Create(square))
self.play(square.animate.rotate(PI / 4))
self.play(Transform(square, circle))
# 创建一个动画,将圆形变成粉色
self.play(circle.animate.set_fill(PINK, opacity=0.5)) 

图片

向量坐标

from manim import *
class VectorArrow(Scene):
    def construct(self):
        dot = Dot(ORIGIN)
        arrow = Arrow(ORIGIN, [220], buff=0)
        number_plane = NumberPlane()
        origin_label = Text("(O,0)").next_to(dot, DOWN)
        arrow_label = Text("(2,2)").next_to(arrow.get_end(), RIGHT)
        self.add(number_plane, dot, arrow, origin_label, arrow_label)

图片

布尔运算

from manim import *
class BooleanOperations(Scene):
    def construct(self):
        ellipse1 = Ellipse(
            width=4.0, height=5.0, fill_opacity=0.5, color=BLUE, stroke_width=10
        ).move_to(LEFT)
        ellipse2 = ellipse1.copy().set_color(color=RED).move_to(RIGHT)
        bool_ops_text = MarkupText("<u>Boolean Operation</u>").next_to(ellipse1, UP * 3)
        ellipse_group = Group(bool_ops_text, ellipse1, ellipse2).move_to(LEFT * 3)
        self.play(FadeIn(ellipse_group))
        i = Intersection(ellipse1, ellipse2, color=GREEN, fill_opacity=0.5)
        self.play(i.animate.scale(0.25).move_to(RIGHT * 5 + UP * 2.5))
        intersection_text = Text("Intersection", font_size=23).next_to(i, UP)
        self.play(FadeIn(intersection_text))
        u = Union(ellipse1, ellipse2, color=ORANGE, fill_opacity=0.5)
        union_text = Text("Union", font_size=23)
        self.play(u.animate.scale(0.3).next_to(i, DOWN, buff=union_text.height * 3))
        union_text.next_to(u, UP)
        self.play(FadeIn(union_text))
        e = Exclusion(ellipse1, ellipse2, color=YELLOW, fill_opacity=0.5)
        exclusion_text = Text("Exclusion", font_size=23)
        self.play(e.animate.scale(0.3).next_to(u, DOWN, buff=exclusion_text.height * 3.5))
        exclusion_text.next_to(e, UP)
        self.play(FadeIn(exclusion_text))
        d = Difference(ellipse1, ellipse2, color=PINK, fill_opacity=0.5)
        difference_text = Text("Difference", font_size=23)
        self.play(d.animate.scale(0.3).next_to(u, LEFT, buff=difference_text.height * 3.5))
        difference_text.next_to(d, UP)
        self.play(FadeIn(difference_text))

图片

在Cursor中使用

实现杠杆原理

@Manim我想使用manim生成一个演示物理杠杆原理的动画
- 符合物理力学原理,演示生动、直观
- 涉及文字说明时默认使用中文

图片

生成完后点击右上角的Manim Sideview预览按钮预览,可以看到有部分文字重叠的情况

图片

可以将问题发给Cursor,让Cursor帮我们处理

杠杆原理动画最后展示杠杆原理文案的时候出现了文字重叠,分析现有代码对布局和文字大小进行合理调整

图片

过程中可能遇到各种不符合要求的问题,我们需要将问题截图和问题详细的描述给AI,有修改建议也可以提供

图片

经过多轮对话,最终得到的演示效果如下:

数学公式推导

@Manim我想使用manim生成一个演示 (a+b)²=a²+2ab+b² 的动画
- 符合数学推导原理,演示生动、直观
- 涉及文字说明时默认使用中文

图片

图片

本以为这个数学公式推导应该难不倒Cursor,没想到还是出现了问题,遇到问题先不慌,将问题反馈给Cursor尝试修改

图片

最终经过多轮对话展示效果如下:

基础版

图片

增强版

交互式版本

项目地址

项目放到Github了,感兴趣的小伙伴可以自行玩耍

Github地址:github.com/MisterZhouZ…

常见问题

No package Cairo found

图片

Manim依赖install,使用brew进行安装

brew install cairo pkg-config

No Such file or directory: latex

图片

LaTeX 是一个非常知名且广泛使用的排版系统,允许我们编排并展示排版公式,出现这个问题意味着您的系统上没有安装 LaTeX,而 Manim 需要它来渲染数学公式。

图片

官方文档地址:docs.manim.community/en/stable/i…

如果我们不想安装MacTex,只是想体验一下Manim,我们可以通过以下命令安装更小、更可定制的 LaTeX 发行版

sudo tlmgr install amsmath babel-english cbfonts-fd cm-super count1to ctex doublestroke dvisvgm everyhook fontspec frcursive fundus-calligra gnu-freefont jknapltx latex-bin mathastex microtype multitoc physics preview prelim2e ragged2e relsize rsfs setspace standalone tipa wasy wasysym xcolor xetex xkeyval

友情提示

见原文:【Cursor实战】Cursor+Manim生成演示动画

本文同步自微信公众号 "程序员小溪" ,这里只是同步,想看及时消息请移步我的公众号,不定时更新我的学习经验。