边学边做Manim中的动点问题

我们在使用Manim制作数学动画的时候,多数会用到点的移动问题,今天我们就来介绍如何制作一个动点,关于点的介绍,大家可以参考博客中的其他文章,这篇文章重点介绍如何移动一个点,来看下面的介绍。

1使用move_to()移动点

我们使用.move_to(),可以让 Dot 移动到另一点,配合动画使用:

1
2
3
4
5
6
7
8
from manim import *

class DotMoveExample(Scene):
def construct(self):
dot = Dot(point=LEFT * 2, radius=0.5)
self.add(dot)
self.play(dot.animate.move_to(RIGHT * 2))
self.wait()

2.使用.move_to() + 轨迹函数

我们还可以使用.move_to() + 轨迹函数的方式,让 Dot 沿着某个路径动:例如从 (0,0) 移动到 (2,3)

1
2
3
4
5
6
7
8
9
from manim import *

class PathExample(Scene):
def construct(self):
dot = Dot(color=GREEN, radius=0.5)
path = Line(ORIGIN, RIGHT * 2 + UP * 1)
self.add(path)
self.play(MoveAlongPath(dot, path), run_time=3)
self.wait()

3.绘制轨迹点

我们还可以绘制轨迹点(追踪)配合 TracedPath 可以绘制 Dot 运动轨迹:

1
2
3
4
5
6
7
8
9
from manim import *

class TracedDot(Scene):
def construct(self):
dot = Dot(RIGHT * 3, radius=0.5)
trace = TracedPath(dot.get_center, stroke_color=RED, stroke_width=2)
self.add(trace)
self.play(Rotating(dot, about_point=ORIGIN, angle=2 * PI), run_time=5)
self.wait()

4.配合坐标系使用

多数情况下,我们还是在坐标系中使用动点,沿着函数图像轨迹运动

1
2
3
4
5
6
7
8
9
10
11
12
from manim import *

class DotWithAxes(Scene):
def construct(self):
axes = Axes()
self.add(axes)
# 创建一个点并放到函数图像上
dot = Dot(point=axes.coords_to_point(1, 1), radius=0.2) # 点 (x=1, y=1)
self.add(dot)
# 动画显示该点移动
self.play(dot.animate.move_to(axes.coords_to_point(2, 4)))
self.wait()

这里使用了 axes.coords_to_point() 方法,将数学坐标系上的点转换为屏幕上的对应点位。

5.Dot 和坐标系的互动

你可以让 Dot 作为坐标系中的点,配合 always_redraw 来实现实时跟踪某个函数的图像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from manim import *

class DotOnGraph(Scene):
def construct(self):
axes = Axes()
graph = axes.plot(lambda x: x**2, color=BLUE)

# 定义一个随 x 改变而移动的 Dot
x = ValueTracker(-2)
dot = always_redraw(lambda: Dot().move_to(axes.c2p(x.get_value(), x.get_value()**2)))
self.add(axes, graph)
self.add(dot)
self.play(x.animate.set_value(2), run_time=4)
self.wait()

在这里介绍一下扩展知识

lambda函数是一种特殊类型的函数,也被叫做匿名函数。匿名意味着它不需要像常规函数那样使用 def 进行命名。lambda函数本质上是简洁的临时函数 ,它适用于只需要简单逻辑的场景,并且通常会在代码里被直接使用,不会像普通函数那样被长期保存和复用。

lambda函数主要用于简化代码结构,它的主要特点是:

  1. • 即用即弃:不需要预先定义
  2. • 简洁性:单行表达式实现功能
  3. • 函数式编程:作为参数传递高阶函数

常用的表达式

1
lambda 参数列表: 表达式

代码中的

1
lambda x: x**2,

就是临时创建一个简单的二次函数。我们会有专门的文章来介绍这个函数的创建过程。今天的教程就到这里,最后点沿着函数图像运动的问题,会有专门的文章来分析介绍。