6.3 项目案例分析
在这一节中,我们将通过具体的项目案例,深入探索 Manim 的潜力,并展示如何使用 Manim 创建复杂且富有表现力的动画。这些案例将涵盖数学、物理以及其他科学领域,帮助您更好地理解和应用 Manim。
6.3.1 案例一:展示数学定理
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| from manim import * class PythagoreanTheorem(Scene): def construct(self): # 创建一个直角三角形 triangle = Polygon(ORIGIN, RIGHT, RIGHT + UP, fill_color=BLUE, fill_opacity=0.5) # 标记各边 a_label = MathTex("a").next_to(triangle, LEFT, buff=0.1) b_label = MathTex("b").next_to(triangle, DOWN, buff=0.1) c_label = MathTex("c").next_to(triangle, UR, buff=0.1) # 显示三角形和标记 self.play(Create(triangle)) self.play(Write(a_label), Write(b_label), Write(c_label)) # 创建方形并标记面积 a_square = Square().scale(0.5).move_to(triangle.get_corner(DL)) b_square = Square().scale(0.5).move_to(triangle.get_corner(DR)) c_square = Square().scale(0.5).move_to(triangle.get_corner(UL)) a_area = MathTex("a^2").move_to(a_square) b_area = MathTex("b^2").move_to(b_square) c_area = MathTex("c^2").move_to(c_square) # 显示方形和面积标记 self.play(Create(a_square), Write(a_area)) self.play(Create(b_square), Write(b_area)) self.play(Create(c_square), Write(c_area)) # 展示公式 formula = MathTex("a^2 + b^2 = c^2").to_edge(UP) self.play(Write(formula)) |
在这个案例中,我们将使用 Manim 来展示毕达哥拉斯定理。我们将通过动画的方式来直观地演示这个定理的证明过程。
解释
|----------------------|
| from manim import * |
从 manim导入所有内容。
|-------------------------------------------------------|
| class PythagoreanTheorem(Scene): def construct(self): |
定义一个名为 PythagoreanTheorem的类,继承自 Scene类。
construct 方法定义了场景内容。
|-----------------------------------------------------------------------------------------------|
| # 创建一个直角三角形 triangle = Polygon( ORIGIN, RIGHT, RIGHT + UP, fill_color=BLUE, fill_opacity=0.5) |
使用 Polygon 创建一个三角形,顶点在 ORIGIN(原点)、RIGHT(向右的一个单位)和 RIGHT + UP(右上角的一个单位)的位置。
设置填充颜色为蓝色,透明度为 0.5。
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # 标记各边 a_label = MathTex("a").next_to(triangle, LEFT, buff=0.1) b_label = MathTex("b").next_to(triangle, DOWN, buff=0.1) c_label = MathTex("c").next_to(triangle, UR, buff=0.1) |
使用 MathTex 创建标签 a、b 和 c,并分别将它们放置在三角形的左侧、下方和右上方(UR)位置,距离为 0.1。
|--------------------------------------------------------------------------------------------------|
| # 显示三角形和标记 self.play(Create(triangle)) self.play(Write(a_label), Write(b_label), Write(c_label)) |
使用 Create 动画绘制三角形。
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # 创建方形并标记面积 a_square = Square().scale(0.5).move_to(triangle.get_corner(DL)) b_square = Square().scale(0.5).move_to(triangle.get_corner(DR)) c_square = Square().scale(0.5).move_to(triangle.get_corner(UL)) |
使用 Write动画显示标签。
使用 Square创建三个方形并缩放至 0.5 倍大小。
将方形分别移动到三角形的左下角(DL)、右下角(DR)和左上角(UL)。
|----------------------------------------------------------------------------------------------------------------------------------|
| a_area = MathTex("a^2").move_to(a_square) b_area = MathTex("b^2").move_to(b_square) c_area = MathTex("c^2").move_to(c_square) |
使用 MathTex 创建面积标记 a^2、b^2 和 c^2,并分别将它们放置在对应的方形中心。
|----------------------------------------------------------------------------------------------------------------------------------------------|
| # 显示方形和面积标记 self.play(Create(a_square), Write(a_area)) self.play(Create(b_square), Write(b_area)) self.play(Create(c_square), Write(c_area)) |
使用 Create 动画绘制方形。
使用 Write 动画显示面积标记。
|--------------------------------------------------------------------------------------|
| # 展示公式 formula = MathTex("a^2 + b^2 = c^2").to_edge(UP) self.play(Write(formula)) |
使用 MathTex 创建毕达哥拉斯定理公式 a^2 + b^2 = c^2,并将其移动到屏幕顶部。
使用 Write动画显示公式。
6.3.2 案例二:模拟物理现象
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| from manim import * class FreeFall(Scene): def construct(self): # 创建一个球体 ball = Circle().set_fill(RED, opacity=0.8).move_to(UP*3) ground = Line(LEFT*5, RIGHT*5).shift(DOWN*3) # 显示地面和球体 self.play(Create(ground)) self.play(Create(ball)) # 自由落体运动 self.play(ball.animate.shift(DOWN*5), rate_func=rate_functions.ease_in_quad, run_time=2) # 加速度和速度标记 accel_label = MathTex("a = 9.8 \\frac{m}{s^2}").to_edge(UP) speed_label = MathTex("v = gt").next_to(ball, RIGHT) self.play(Write(accel_label)) self.play(Write(speed_label)) |
代码示例
解释
|----------------------|
| from manim import * |
从 manim导入所有内容。
|---------------------------------------------|
| class FreeFall(Scene): def construct(self): |
定义一个名为 FreeFall的类,继承自 Scene类。
|--------------------------------------------------------------------------------------------------------------------|
| # 创建一个球体 ball = Circle().set_fill(RED, opacity=0.8).move_to(UP*3) ground = Line(LEFT*5, RIGHT*5).shift(DOWN*3) |
construct方法定义了场景内容。
使用 Circle创建一个红色的球体,透明度为 0.8,并将其移动到屏幕上方。
|-------------------------------------------------------------|
| # 显示地面和球体 self.play(Create(ground)) self.play(Create(ball)) |
使用 Line创建一条线作为地面,长度为 10(从左到右各 5 个单位),并将其向下移动 3 个单位。
|----------------------------------------------------------------------------------------------------|
| # 自由落体运动 self.play(ball.animate.shift(DOWN*5), rate_func=rate_functions.ease_in_quad, run_time=2) |
使用 Create动画绘制地面和球体。
使用 animate和 shift方法将球体向下移动 5 个单位,使用 ease_in_quad作为速率函数,运行时间为 2 秒。
|--------------------------------------------------------------------------------------------------------------------------------|
| # 加速度和速度标记 accel_label = MathTex("a = 9.8 \\frac{m}{s^2}").to_edge(UP) speed_label = MathTex("v = gt").next_to(ball, RIGHT) |
使用 MathTex创建加速度标记 a = 9.8 \frac{m}{s^2}并将其移动到屏幕顶部。
|-------------------------------------------------------------|
| self.play(Write(accel_label)) self.play(Write(speed_label)) |
使用 MathTex创建速度标记 v = gt并将其放置在球体的右侧。
使用 Write动画显示加速度和速度标记。
6.3.3 案例三:可视化数据分析
代码示例
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| from manim import * class BarChart(Scene): def construct(self): # 创建轴 axes = Axes(x_range=[0, 5, 1], y_range=[0, 10, 2], axis_config={"color": BLUE} ) # 创建柱状图 bars = VGroup() heights = [6, 7, 3, 5, 9] for i, height in enumerate(heights): bar = Rectangle(width=0.5, height=height, fill_color=GREEN, fill_opacity=0.8) bar.next_to(axes.c2p(i + 1, 0), UP, buff=0) bars.add(bar) # 显示轴和柱状图 self.play(Create(axes)) self.play(LaggedStart(*[GrowFromEdge(bar, DOWN) for bar in bars], lag_ratio=0.1)) # 添加数据标记 labels = VGroup(*[MathTex(str(height)).next_to(bar, UP, buff=0.1) for height, bar in zip(heights, bars)]) self.play(LaggedStart(*[Write(label) for label in labels], lag_ratio=0.1)) |
解释
|---------------------------------------------|
| class BarChart(Scene): def construct(self): |
定义一个名为BarChart的类,继承自Scene类。
|-------------------------------------------------------------------------------------------|
| # 创建轴 axes = Axes(x_range=[0, 5, 1], y_range=[0, 10, 2], axis_config={"color": BLUE}) |
construct方法定义了场景内容。
使用 Axes创建一个坐标轴,x 轴范围为 0 到 5,步长为 1;y 轴范围为 0 到 10,步长为 2
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # 创建柱状图 bars = VGroup() heights = [6, 7, 3, 5, 9] for i, height in enumerate(heights): bar = Rectangle(width=0.5, height=height, fill_color=GREEN, fill_opacity=0.8) bar.next_to(axes.c2p(i + 1, 0), UP, buff=0) bars.add(bar) |
设置轴的颜色为蓝色。
使用 VGroup创建一个组来容纳所有的柱形条。
定义每个柱形条的高度为 `heights` 列表中的值。
使用 `Rectangle创建柱形条,宽度为 0.5,高度为 height,填充颜色为绿色,透明度为 0.8。
使用 next_to方法将每个柱形条放置在相应的 x 轴位置。
|------------------------------------------------------------------------------------------------------------------------|
| # 显示轴和柱状图 self.play(Create(axes)) self.play(LaggedStart(*[GrowFromEdge(bar, DOWN) for bar in bars], lag_ratio=0.1)) |
将每个柱形条添加到bars 组中。
使用 Create动画绘制坐标轴。
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # 添加数据标记 labels = VGroup(*[MathTex(str(height)).next_to(bar, UP, buff=0.1) for height, bar in zip(heights, bars)]) self.play(LaggedStart(*[Write(label) for label in labels], lag_ratio=0.1)) |
使用 LaggedStart逐个显示柱形条,从下到上生长,每个柱形条之间有 0.1 的延迟。
使用 VGroup创建一个组来容纳所有的高度标签。
使用 MathTex创建高度标签,将其放置在相应的柱形条上方。
使用LaggedStart逐个显示高度标签,每个标签之间有 0.1 的延迟。
总结
通过上述三个案例,我们展示了如何使用 Manim 来创建数学定理演示、物理现象模拟以及数据可视化。这些案例不仅展示了 Manim 的强大功能,也为您提供了实践参考,帮助您在自己的项目中应用 Manim。
展示数学定理:通过动画展示几何定理的证明过程,使抽象的数学概念更加直观易懂。
模拟物理现象:通过动画模拟物理现象,可以更好地理解物理概念和原理。
可视化数据分析:通过动画展示数据变化和趋势,帮助更好地理解和分析数据。
在接下来的章节中,我们将进一步探讨 Manim 的高级用法以及优化技巧,帮助您更高效地制作动画。