在数学教学中,勾股定理是几何学的基石。今天,我们用Manim动画库将这个经典定理以可视化的方式呈现出来,让抽象的数学公式变得生动有趣。
from manim import *# ==============================# 1920x1080 横屏参数# ==============================config.pixel_width = 1920config.pixel_height = 1080config.frame_width = 16config.frame_height = 9class TestDouyin(Scene): def construct(self): # ====================================================== # ① 全局参数与现代配色 # ====================================================== T_SPEED = 1.5 # <--- 节奏控制变量:值越小越快,值越大越慢 SCALE_FACTOR = 1.1 # 现代极简调色盘 C_A = "#58C4DD" # 浅蓝 C_B = "#83C167" # 苹果绿 C_C = "#FF8080" # 珊瑚色 C_TRI = [C_A, C_B, "#5181B8", "#699175"] HL_COLOR = "#F4D03F" # 琥珀金 a_val, b_val = 2.0, 2.8 side_len = a_val + b_val # ====================================================== # ② 几何体构建 (左侧) # ====================================================== # 虚拟一个大正方形作为对齐参考 temp_sq = Square(side_length=side_len) pts = [ [temp_sq.get_corner(UL), temp_sq.get_corner(UL) + RIGHT * a_val, temp_sq.get_corner(UL) + DOWN * b_val], [temp_sq.get_corner(UR), temp_sq.get_corner(UR) + DOWN * a_val, temp_sq.get_corner(UR) + LEFT * b_val], [temp_sq.get_corner(DR), temp_sq.get_corner(DR) + LEFT * a_val, temp_sq.get_corner(DR) + UP * b_val], [temp_sq.get_corner(DL), temp_sq.get_corner(DL) + UP * a_val, temp_sq.get_corner(DL) + RIGHT * b_val], ] triangles = VGroup(*[ Polygon(*p, fill_opacity=0.7, color=C_TRI[i], stroke_width=2) for i, p in enumerate(pts) ]) center_square = Polygon( *[p[1] for p in pts], color=WHITE, fill_opacity=0.15, stroke_width=2 ) label_center_c = MathTex("c^2", font_size=72, color=WHITE).move_to(center_square.get_center()) # 标注更加精致 brace_a = BraceBetweenPoints(pts[0][0], pts[0][1], UP, buff=0.1) label_a = brace_a.get_tex("a").scale(0.9) brace_b = BraceBetweenPoints(pts[0][0], pts[0][2], LEFT, buff=0.1) label_b = brace_b.get_tex("b").scale(0.9) geometry = VGroup(triangles, center_square, label_center_c, brace_a, label_a, brace_b, label_b) # ====================================================== # ③ 推导文字 (右侧) # ====================================================== # 使用相同字号保持统一感 fs = 42 f1 = VGroup( Text("大正方形面积", font_size=fs-8, weight=BOLD), MathTex("S = (a+b)^2", font_size=fs+8) ).arrange(DOWN, aligned_edge=LEFT, buff=0.2) f2 = MathTex("= 4 \\cdot \\frac{1}{2}ab + c^2", font_size=fs+8) f3 = MathTex("a^2 + 2ab + b^2 = 2ab + c^2", font_size=fs) f4 = MathTex("a^2 + b^2 = c^2", font_size=fs+40, color=HL_COLOR) # 将公式垂直排列 formulas = VGroup(f1, f2, f3, f4).arrange(DOWN, buff=0.6, aligned_edge=LEFT) # 对齐 = 号 f2.align_to(f1[1][0][1], LEFT).shift(RIGHT * 0.3) # ====================================================== # ④ 布局优化:将左右两部分组合并居中 # ====================================================== all_content = VGroup(geometry, formulas).arrange(RIGHT, buff=1.5).center().scale(SCALE_FACTOR) # ====================================================== # ⑤ 动画流程 # ====================================================== # 1. 拼图 self.play( LaggedStart( *[FadeIn(tri, shift=tri.get_center()*0.2) for tri in triangles], lag_ratio=0.15, run_time=1.5 * T_SPEED ) ) self.play( Create(VGroup(brace_a, brace_b), run_time=1.0 * T_SPEED), Write(VGroup(label_a, label_b), run_time=1.0 * T_SPEED) ) self.wait(0.2 * T_SPEED) # 2. 中心 self.play( Create(center_square, run_time=1.0 * T_SPEED), Write(label_center_c, run_time=1.0 * T_SPEED) ) self.play( label_center_c.animate.set_color(HL_COLOR).scale(1.1), rate_func=there_and_back, run_time=1.0 * T_SPEED ) # 3. 逐步推导 self.play(Write(f1, run_time=1.0 * T_SPEED)) self.wait(0.5 * T_SPEED) self.play(Write(f2, run_time=1.0 * T_SPEED)) self.play( f1.animate.set_opacity(0.4), f2.animate.set_opacity(0.4), run_time=1.0 * T_SPEED ) self.play(Write(f3, run_time=1.0 * T_SPEED)) self.wait(0.8 * T_SPEED) # 4. 终极结论 self.play( f3.animate.set_opacity(0.2), ReplacementTransform(f3.copy(), f4), run_time=1.5 * T_SPEED ) self.play(Indicate(f4, color=HL_COLOR, scale_factor=1.1, run_time=1.5 * T_SPEED)) self.wait(3 * T_SPEED)这段代码使用Manim创建了一个1920×1080的横屏动画,通过几何图形的动态演示来证明勾股定理(a² + b² = c²)。
核心思路是利用"弦图"证明法:在一个边长为(a+b)的大正方形内,放置4个相同的直角三角形,中间留出一个边长为c的小正方形。通过面积等式推导,最终得出勾股定理。
几何构建:代码精心设计了4个直角三角形的位置,分别位于大正方形的四个角,每个三角形的直角边长度为a和b。中心形成的正方形边长恰好等于斜边c。配色采用现代极简风格,使用浅蓝、苹果绿等柔和色调。
动画编排:整个演示分为4个阶段——
节奏控制:通过T_SPEED参数(默认1.5)可以灵活调整动画快慢,适应不同场景需求。
Square、Polygon创建图形,BraceBetweenPoints添加标注FadeIn淡入、Create绘制、Write书写、ReplacementTransform变换Indicate强调、LaggedStart错位启动,there_and_back往返动画VGroup组合对象,arrange智能排列,align_to对齐这个项目完美展示了编程与数学的结合,让古老的定理焕发新的生命力。无论是教学演示还是科普视频,都是极佳的素材。
from manim import *# ==============================# 1080x1920 竖屏参数# ==============================config.pixel_width = 1080config.pixel_height = 1920config.frame_width = 9config.frame_height = 16class TestDouyin(Scene): def construct(self): # ====================================================== # ① 全局参数与节奏控制 (T_SPEED) # ====================================================== T_SPEED = 1.5 # <--- 节奏控制变量:值越小越快,值越大越慢 SCALE_FACTOR = 1.15 C_A = "#58C4DD" # 浅蓝 C_B = "#83C167" # 苹果绿 C_TRI = ["#58C4DD", "#83C167", "#5181B8", "#699175"] HL_COLOR = "#F4D03F" # 琥珀金 a_val, b_val = 2.0, 2.8 side_len = a_val + b_val # ====================================================== # ② 几何体构建 # ====================================================== temp_sq = Square(side_length=side_len) pts = [ [temp_sq.get_corner(UL), temp_sq.get_corner(UL) + RIGHT * a_val, temp_sq.get_corner(UL) + DOWN * b_val], [temp_sq.get_corner(UR), temp_sq.get_corner(UR) + DOWN * a_val, temp_sq.get_corner(UR) + LEFT * b_val], [temp_sq.get_corner(DR), temp_sq.get_corner(DR) + LEFT * a_val, temp_sq.get_corner(DR) + UP * b_val], [temp_sq.get_corner(DL), temp_sq.get_corner(DL) + UP * a_val, temp_sq.get_corner(DL) + RIGHT * b_val], ] triangles = VGroup(*[ Polygon(*p, fill_opacity=0.7, color=C_TRI[i], stroke_width=2) for i, p in enumerate(pts) ]) center_square = Polygon( *[p[1] for p in pts], color=WHITE, fill_opacity=0.15, stroke_width=2 ) label_center_c = MathTex("c^2", font_size=80).move_to(center_square.get_center()) brace_a = BraceBetweenPoints(pts[0][0], pts[0][1], UP, buff=0.1) label_a = brace_a.get_tex("a").scale(1.0) brace_b = BraceBetweenPoints(pts[0][0], pts[0][2], LEFT, buff=0.1) label_b = brace_b.get_tex("b").scale(1.0) geometry = VGroup(triangles, center_square, label_center_c, brace_a, label_a, brace_b, label_b) # ====================================================== # ③ 文字推导 # ====================================================== fs = 48 f1 = VGroup( Text("大正方形面积", font_size=fs-10, weight=BOLD), MathTex("S = (a+b)^2", font_size=fs+10) ).arrange(RIGHT, buff=0.3) f2 = MathTex("= 4 \\cdot \\frac{1}{2}ab + c^2", font_size=fs+10) f3 = MathTex("a^2 + 2ab + b^2 = 2ab + c^2", font_size=fs-4) f4 = MathTex("a^2 + b^2 = c^2", font_size=fs+50, color=HL_COLOR) formulas = VGroup(f1, f2, f3, f4).arrange(DOWN, buff=0.7) # 整体布局 all_content = VGroup(geometry, formulas).arrange(DOWN, buff=1.5).center().scale(SCALE_FACTOR) # ====================================================== # ④ 动画流程 # ====================================================== # 1. 拼图进场 self.play( LaggedStart( *[FadeIn(tri, shift=tri.get_center()*0.3) for tri in triangles], lag_ratio=0.15, run_time=1.5 * T_SPEED ) ) self.play( Create(VGroup(brace_a, brace_b), run_time=1.0 * T_SPEED), Write(VGroup(label_a, label_b), run_time=1.0 * T_SPEED) ) # 2. 内部正方形提示 self.play( Create(center_square, run_time=1.0 * T_SPEED), Write(label_center_c, run_time=0.8 * T_SPEED) ) self.play(Indicate(label_center_c, color=HL_COLOR, scale_factor=1.2, run_time=1.0 * T_SPEED)) self.wait(0.3 * T_SPEED) # 3. 算式推导 self.play(Write(f1, run_time=1.2 * T_SPEED)) self.wait(0.4 * T_SPEED) self.play(Write(f2, run_time=1.2 * T_SPEED)) # 变暗前两行,引出第三行 self.play( f1.animate.set_opacity(0.3), f2.animate.set_opacity(0.3), run_time=0.8 * T_SPEED ) self.play(Write(f3, run_time=1.5 * T_SPEED)) self.wait(0.8 * T_SPEED) # 4. 结论变换 self.play( f1.animate.set_opacity(0.3), f2.animate.set_opacity(0.3), f3.animate.set_opacity(0.3), ReplacementTransform(f3.copy(), f4), run_time=1.5 * T_SPEED ) # 5. 强调最终结论 self.play( Circumscribe(f4, color=HL_COLOR, buff=0.2, run_time=1.5 * T_SPEED), f4.animate(run_time=1.0 * T_SPEED).scale(1.1) ) self.wait(3 * T_SPEED)关键词: Manim动画 | 勾股定理 | 可视化证明 | Python数学 | 几何动画 | 数学教学 | 弦图证明法 | 编程教育 | 科普动画