网站首页 > 技术文章 正文
3Blue1Brown介绍
3Blue1Brown是由Grant Sanderson打造的数学、ai等概念讲解的视频频道,他的每个视频都配有生动又直观的数学动画。
很多观众喜爱他的原因大概就是他那些数学动画,因此如果你也想做相关的数学动画而又无从下手的话,由Grant Sanderson自己开源的数学动画开源库manim将会帮助你制作简洁、生动的数学动画。
展示视频
如果不想看代码分解过程的,可以直接拉到底部看完整代码。
版本说明
目前Grant Sanderson开源了两个版本库,分别是:manim和manimgl。
本文是针对mainm的案例教程,请勿选择错误。
安装下载
github地址:
https://github.com/ManimCommunity/manim
pip安装:
pip install manim
勾股定理案例详情
1.1 前期准备
本文是一个勾股定理说明的数学动画案例,创建一个test.py作为测试脚本:
1.2 动画思路
最出名的勾股定理是3^2+4^2=5^2,因此我将构造三个正方形,分别是边长为3、边长为4和边长为5。
之后我将会把正方形变换为等面积的长方形分别是:长4.5,高2;长8,高2;长12.5,高2。
最后将长4.5与长8的长方形左右拼接,将长12.5的长方形覆盖其上,证明勾股定理。
1.3 创建场景
manim是基于面向对象的,因此是通过类的实现来创建不同的动画,以下是场景代码:
from manim import *
class PythagoreanTheorem(Scene):
def construct(self):
pass
之后我们将在构造方法construct编写我们的动画代码。
1.4 创建正方形
我们将创建三个正方形放置在场景的偏上方的位置,边长分别为3、4、5,颜色为蓝色、绿色和红色:
square_a = Square(side_length=3, color=BLUE).shift(UP)
square_b = Square(side_length=4, color=GREEN).shift(UP)
square_c = Square(side_length=5, color=RED).shift(UP)
1.5 创建文本到正方形内部
label_a = MathTex("a^2").move_to(square_a.get_center())
label_b = MathTex("b^2").move_to(square_b.get_center())
label_c = MathTex("c^2").move_to(square_c.get_center())
这里使用MathTex来创建数学公式文本,再通过move_to进行移动,而移动的位置是相应图形的get_center(),正是中间位置。
- get_center():返回的是Point3D类,它继承于numpy的ndarray
除了使用MathTex来创建数学公式的字符串,还可以通过Tex来实现,如下:
label_a = Tex('$a^2#39;).move_to(square_a.get_center())
label_b = Tex('$b^2#39;).move_to(square_b.get_center())
label_c = Tex('$c^2#39;).move_to(square_c.get_center())
被 $ 符号包裹的部分将转换为数学公式,使用起来更加灵活。
1.6 播放正方形和文本
self.play(Create(square_a), Write(label_a))
self.play(Create(square_b), Write(label_b))
self.play(Create(square_c), Write(label_c))
self.wait(2)
播放使用的是 self.play() 方法,在这里我们播放时创建了正方形的同时写出公式,在结尾让视频 self.wait(2) 暂停2秒后结束。
保存后查看当前代码:
from manim import *
classPythagoreanTheorem(Scene):
defconstruct(self):
square_a = Square(side_length=3, color=BLUE).shift(UP)
square_b = Square(side_length=4, color=GREEN).shift(UP)
square_c = Square(side_length=5, color=RED).shift(UP)
label_a = Tex('$a^2#39;).move_to(square_a.get_center())
label_b = Tex('$b^2#39;).move_to(square_b.get_center())
label_c = Tex('$c^2#39;).move_to(square_c.get_center())
self.play(Create(square_a), Write(label_a))
self.play(Create(square_b), Write(label_b))
self.play(Create(square_c), Write(label_c))
self.wait(2)
现在需要在命令行进行视频的生成:
manim -pql test.py PythagoreanTheorem
-pql说明:
- -p:预览
- -q:视频质量
- -l:低质量
因此使用 -pql 后,将输出低质量的视频并进行预览。
可以看到视频中图形的播放顺序和我们写代码的顺序是一致的,它是串行的关系。
1.7 创建长方形,并将正方形变换为长方形
rect_a = Rectangle(width=4.5, height=2).shift(UP)
rect_a.set_fill(BLUE, opacity=0.8)
rect_b = Rectangle(width=8, height=2).shift(UP)
rect_b.set_fill(GREEN, opacity=0.8)
rect_c = Rectangle(width=12.5, height=2, color=RED).shift(UP)
创建了三个长方形,其中a和b是填充了背景色,c要进行覆盖,只画了边框颜色。
接下来将正方形转换为长方形:
self.play(Create(square_a), Write(label_a))
self.play(ReplacementTransform(square_a, rect_a))
self.play(Create(square_b), Write(label_b))
self.play(ReplacementTransform(square_b, rect_b))
self.play(Create(square_c), Write(label_c))
self.play(ReplacementTransform(square_c, rect_c))
查看视频:
1.8 缩放动画
目前看图形略大,占屏幕比较多,希望缩小一点,可以使用下面代码:
self.play(Create(square_a), Write(label_a))
self.play(ReplacementTransform(square_a, rect_a))
self.play(rect_a.animate.scale(0.5))
self.play(Create(square_b), Write(label_b))
self.play(ReplacementTransform(square_b, rect_b))
self.play(rect_b.animate.scale(0.5))
self.play(Create(square_c), Write(label_c))
self.play(ReplacementTransform(square_c, rect_c))
self.play(rect_c.animate.scale(0.5))
查看视频:
1.9 移动图形
接下来需要将之前创建的图像往上挪一挪,全部叠在一块儿不好看:
self.play(Create(square_a), Write(label_a))
self.play(ReplacementTransform(square_a, rect_a))
self.play(rect_a.animate.scale(0.5))
self.play(rect_a.animate.shift(UP * 2))
self.play(Create(square_b), Write(label_b))
self.play(ReplacementTransform(square_b, rect_b))
self.play(rect_b.animate.scale(0.5))
self.play(rect_b.animate.shift(UP))
self.play(Create(square_c), Write(label_c))
self.play(ReplacementTransform(square_c, rect_c))
self.play(rect_c.animate.scale(0.5))
查看视频:
1.10 文字移动
图形移动后,文字未动,因此要将文字一并做修改:
self.play(Create(square_a), Write(label_a))
label_a.add_updater(lambda m: m.move_to(rect_a.get_center()))
self.play(ReplacementTransform(square_a, rect_a))
self.play(rect_a.animate.scale(0.5))
self.play(rect_a.animate.shift(UP * 2))
self.play(Create(square_b), Write(label_b))
label_b.add_updater(lambda m: m.move_to(rect_b.get_center()))
self.play(ReplacementTransform(square_b, rect_b))
self.play(rect_b.animate.scale(0.5))
self.play(rect_b.animate.shift(UP))
self.play(Create(square_c), Write(label_c))
label_c.add_updater(lambda m: m.move_to(rect_c.get_center()))
self.play(ReplacementTransform(square_c, rect_c))
self.play(rect_c.animate.scale(0.5))
查看视频:
完整代码
from manim import *
classPythagoreanTheorem(Scene):
defconstruct(self):
square_a = Square(side_length=3, color=BLUE).shift(UP)
rect_a = Rectangle(width=4.5, height=2).shift(UP)
rect_a.set_fill(BLUE, opacity=0.8)
square_b = Square(side_length=4, color=GREEN).shift(UP)
rect_b = Rectangle(width=8, height=2).shift(UP)
rect_b.set_fill(GREEN, opacity=0.8)
square_c = Square(side_length=5, color=RED).shift(UP)
rect_c = Rectangle(width=12.5, height=2, color=RED).shift(UP)
label_a = Tex('$a^2#39;).move_to(square_a.get_center())
label_b = Tex('$b^2#39;).move_to(square_b.get_center())
label_c = Tex('$c^2#39;).move_to(square_c.get_center())
self.play(Create(square_a), Write(label_a))
label_a.add_updater(lambda m: m.move_to(rect_a.get_center()))
self.play(ReplacementTransform(square_a, rect_a))
self.play(rect_a.animate.scale(0.5))
self.play(rect_a.animate.shift(UP * 2))
self.play(Create(square_b), Write(label_b))
label_b.add_updater(lambda m: m.move_to(rect_b.get_center()))
self.play(ReplacementTransform(square_b, rect_b))
self.play(rect_b.animate.scale(0.5))
self.play(rect_b.animate.shift(UP))
self.play(Create(square_c), Write(label_c))
label_c.add_updater(lambda m: m.move_to(rect_c.get_center()))
self.play(ReplacementTransform(square_c, rect_c))
self.play(rect_c.animate.scale(0.5))
self.play(rect_a.animate.shift(LEFT * 2))
self.play(rect_b.animate.next_to(rect_a, RIGHT, 0))
self.play(rect_c.animate.shift(UP * 2))
# 创建勾股定理公式
theorem = Tex("$a^2 + b^2 = c^2#34;).next_to(rect_c.get_bottom(), DOWN, aligned_edge=ORIGIN)
self.play(Write(theorem))
self.wait(2)
结尾
manim是一个非常有意思的库,其编码思想也很有动画思维。
如果这篇文章点赞超过100,我将继续研究manim,给大家带来更多的manim案例文章。
猜你喜欢
- 2025-07-01 SQLAlchemy数据库框架 和数据库打交道好开心呢
- 2025-07-01 Python 之 turtle 画 033--《海贼王》~ 路飞的海贼旗简笔画
- 2025-07-01 30个小时搞定Python网络爬虫(全套详细版)
- 2025-07-01 别到处借会员了,这里啥都有!高清全免费
- 2025-07-01 程序员思维修图!python库去背景,只需一行代码海量图片回车搞定
- 2025-07-01 8个python自学网站,一周就可以练熟Python,真的是是小白的福音
- 2025-07-01 python 字符串的定义和表示(python字符串怎么定义)
- 2025-07-01 Python爬虫,高清美图我全都要!爬取你想要的,嘿嘿嘿
- 2025-07-01 python中random的使用(random python怎么用)
- 2025-07-01 动漫服装怎么画?分解各种动漫服饰中的小单件绘画素材
- 277℃Python短文,Python中的嵌套条件语句(六)
- 276℃python笔记:for循环嵌套。end=""的作用,图形打印
- 273℃PythonNet:实现Python与.Net代码相互调用!
- 268℃Python实现字符串小写转大写并写入文件
- 267℃Python操作Sqlserver数据库(多库同时异步执行:增删改查)
- 126℃原来2025是完美的平方年,一起探索六种平方的算吧
- 110℃Ollama v0.4.5-v0.4.7 更新集合:Ollama Python 库改进、新模型支持
- 108℃Python 和 JavaScript 终于联姻了!PythonMonkey 要火?
- 最近发表
-
- 假期苦短,我用Python!这有个自动回复拜年信息的小程序
- 第4天|16天搞定Python数据分析,图表,靓靓靓
- 60带源代码的Python项目之 08 使用 Python 生成 QR 码
- 用python3 实现生成二维码代码示例
- python批量生成二维码图片(python如何生成二维码)
- 使用python生成二维码(python生成二维码界面)
- Python制作二维码(python制作二维码小作业)
- Python 生成条形码、二维码 (Code 128、EAN-13、QR code等)
- python如何实现二维码的生成和识别
- Python 使用 JsonPath 完成接口自动化测试中参数关联和数据验证
- 标签列表
-
- python中类 (31)
- python 迭代 (34)
- python 小写 (35)
- python怎么输出 (33)
- python 日志 (35)
- python语音 (31)
- python 工程师 (34)
- python3 安装 (31)
- python音乐 (31)
- 安卓 python (32)
- python 小游戏 (32)
- python 安卓 (31)
- python聚类 (34)
- python向量 (31)
- python大全 (31)
- python次方 (33)
- python桌面 (32)
- python总结 (34)
- python浏览器 (32)
- python 请求 (32)
- python 前端 (32)
- python验证码 (33)
- python 题目 (32)
- python 文件写 (33)
- python中的用法 (32)