当前位置:首页>python>用Python动画演示勾股定理:让数学"动"起来(赵爽弦图)

用Python动画演示勾股定理:让数学"动"起来(赵爽弦图)

  • 2026-10-21 13:29:01
用Python动画演示勾股定理:让数学"动"起来(赵爽弦图)

用Python动画演示勾股定理:让数学"动"起来(赵爽弦图)

在数学教学中,勾股定理是几何学的基石。今天,我们用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个阶段——

  1. 1. 四个三角形依次淡入,展现拼图效果
  2. 2. 标注边长a、b,绘制中心正方形并标记c²
  3. 3. 右侧逐步推导数学公式:从(a+b)²展开
  4. 4. 最终以琥珀金色高亮显示结论a² + b² = c²

节奏控制:通过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数学 | 几何动画 | 数学教学 | 弦图证明法 | 编程教育 | 科普动画

最新文章

随机文章