本文将介绍如何使用Manim
框架实现镜面反射特效,让你的动画更加生动有趣。
1. 实现原理
1.1. 对称点计算
实现镜面反射的核心是计算点关于直线的对称点。
代码中的symmetry_point
函数通过向量投影的方法计算对称点:
python
# 关于直线的对称点
# p1和p2在直线l上,计算p关于l的对称点
def symmetry_point(p1, p2, p):
"""
计算点p关于由两点p1和p2确定的直线的对称点
参数:
p1, p2 : 直线上的两点 (numpy array or list)
p : 直线外的点 (numpy array or list)
返回:
对称点坐标 (numpy array)
"""
# 转换为numpy数组确保计算正确
p1 = np.array(p1)
p2 = np.array(p2)
p = np.array(p)
# 计算直线的方向向量
direction = p2 - p1
# 计算从p1到p的向量
vec_p1p = p - p1
# 计算投影长度(点p在直线上的投影点到p1的距离)
proj_length = np.dot(vec_p1p, direction) / np.dot(direction, direction)
# 计算点p在直线上的投影点
projection = p1 + proj_length * direction
# 对称点 = 2 * 投影点 - 原点
symmetric_point = 2 * projection - p
return np.array([symmetric_point[0], symmetric_point[1], 0])
这个函数使用了向量投影的数学原理,先找到点在直线上的投影,然后根据投影点计算对称点。具体步骤是:
- 计算直线的方向向量
- 计算从直线上一点到目标点的向量
- 计算该向量在直线方向上的投影长度
- 找到投影点坐标
- 通过公式
2 * 投影点 - 原点
计算对称点
1.2. 反射动画类设计
MirrorReflection
类继承自Manim的 Animation
类,用于创建和管理镜面反射效果:
python
# 镜面反射动画类
class MirrorReflection(Animation):
def __init__(
self,
mobject,
mirror: Line = None,
reflect_opacity=0.3,
reflect_stroke_opacity=0.5,
**kwargs,
):
# 初始化参数
self.original = mobject
self.mirror = mirror if mirror else Line(LEFT, RIGHT)
self.reflect_opacity = reflect_opacity
self.reflect_stroke_opacity = reflect_stroke_opacity
# 创建反射对象并设置初始属性
self.reflection = mobject.copy()
self._update_reflection_position()
self.reflection.set_fill(opacity=self.reflect_opacity * mobject.get_fill_opacity())
self.reflection.set_stroke(opacity=self.reflect_stroke_opacity * mobject.get_stroke_opacity())
# 添加动态更新器
self.reflection.add_updater(self._update_reflection)
super().__init__(mobject, **kwargs)
1.3. 动态更新机制
为了确保反射效果能够跟随原始对象的变化而实时更新,代码实现了几个关键方法:
python
def _update_reflection_position(self):
"""更新反射对象的位置"""
points = self.original.get_points()
new_points = []
p1, p2 = self.mirror.get_start(), self.mirror.get_end()
for p in points:
# 使用对称点计算函数计算每个点的反射位置
new_points.append(symmetry_point(p1, p2, p))
# 应用新位置
self.reflection.set_points(new_points)
def _update_reflection(self, reflection_mobject):
"""更新反射对象的属性"""
# 重新创建反射对象并应用垂直翻转
temp_reflection = self.original.copy()
reflection_mobject.become(temp_reflection)
# 更新反射对象位置和透明度
self._update_reflection_position()
reflection_mobject.set_fill(opacity=self.reflect_opacity * self.original.get_fill_opacity())
reflection_mobject.set_stroke(opacity=self.reflect_stroke_opacity * self.original.get_stroke_opacity())
这些方法确保了无论原始对象如何移动、缩放或旋转,反射效果都会相应地更新,保持视觉上的一致性。
2. 使用示例
让我们看看如何在实际场景中使用这个镜面反射特效:
python
# 使用示例
class Example(Scene):
def construct(self):
# 创建三角形对象
triangle = Triangle(color=BLUE)
triangle.shift(2 * LEFT)
# 创建垂直镜面
mirror = Line(UP * 3, DOWN * 3, color=WHITE)
# 创建镜面反射动画
mirror_reflection = MirrorReflection(triangle, mirror=mirror)
reflection = mirror_reflection.create_reflection_mobject()
# 添加到场景
self.add(mirror, triangle, reflection)
self.wait()
# 动画演示
self.play(triangle.animate.shift(UP))
self.wait()
self.play(triangle.animate.scale(1.5))
self.wait()
self.play(triangle.animate.shift(DOWN))
self.wait()
self.play(Rotate(triangle, angle=PI))
self.wait()
使用步骤非常简单:
- 创建需要添加反射效果的原始对象(这里是一个蓝色三角形)
- 创建镜面(这里是一条白色垂直线)
- 创建
MirrorReflection
实例,并传入原始对象和镜面 - 通过
create_reflection_mobject()
方法获取反射对象 - 将原始对象、镜面和反射对象添加到场景中
- 对原始对象执行各种动画操作,观察反射效果的实时更新
在这个例子中,我们演示了对象的上移、缩放、下移和旋转四种操作,反射效果都会实时跟随更新,保持与原始对象的对称关系。

3. 总结
3.1. 特效特点
这个镜面反射特效具有以下特点:
- 实时更新:无论原始对象如何变换,反射效果都会实时更新,保持视觉一致性
- 高度可定制:可以调整反射对象的填充透明度和描边透明度,创建不同的视觉效果
- 灵活的镜面设置:可以自定义镜面的位置、方向和样式,适应不同场景需求
- 易用性:封装成了独立的动画类,使用简单,只需几行代码就能添加专业的反射效果
3.2. 使用场景
镜面反射特效适用于多种场景:
- 数学教学:用于几何对称、坐标系变换等概念的可视化教学
- 物理模拟:模拟光的反射、镜像对称等物理现象
- 艺术效果:为动画添加美感和层次感,提升视觉吸引力
- 交互演示:用于展示对称关系、变换过程等
- Logo和品牌展示:创建镜像效果的动态Logo动画
通过这个简单而强大的镜面反射特效,可以为你的Manim
动画增添更多的视觉魅力和专业感。