from manim import * class PythagoreanProof(Scene): def construct(self): # 场景1:问题引入 # 创建直角三角形 tri = Polygon([-2, -1, 0], [1, -1, 0], [-2, 2, 0], color=WHITE) labels = VGroup( Tex("a", color=RED).next_to(tri.get_vertices()[1], DOWN), Tex("b", color=BLUE).next_to(tri.get_vertices()[2], LEFT), Tex("c", color=GREEN).next_to(tri.get_midpoint(), UR, buff=0.3) ) self.play(Create(tri), run_time=2) self.play(Write(labels), run_time=1.5) # 显示平方表达式 equation = VGroup( Tex("a^2 + b^2 = ?", color=RED_B).shift(UP * 2), Tex("c^2 = ?", color=GREEN_B).shift(DOWN * 2) ) arrows = VGroup( Arrow(equation[0].get_bottom(), labels[0].get_center() + DOWN * 0.5, color=RED), Arrow(equation[0].get_bottom(), labels[1].get_center() + LEFT * 0.5, color=BLUE), Arrow(equation[1].get_top(), labels[2].get_center() + UR * 0.3, color=GREEN) ) self.play(Write(equation), run_time=1.5) self.play(LaggedStart(*[GrowArrow(a) for a in arrows]), run_time=2) self.wait(1) # 场景2:构造辅助图形 # 创建三个正方形 square_a = Square(side_length=2, color=RED).next_to(tri, LEFT, buff=0) square_b = Square(side_length=3, color=BLUE).next_to(tri, DOWN, buff=0) square_c = Square(side_length=np.sqrt(13), color=GREEN).rotate(np.arctan(3 / 2)).next_to(tri, UR, buff=0) for s, t in zip([square_a, square_b, square_c], ["a^2", "b^2", "c^2"]): s.set_fill(opacity=0.2) self.play(Create(s), Write(Tex(t).move_to(s.get_center())), run_time=1.5) # 镜头聚焦 self.play( self.camera.frame.animate.set_width(square_a.width * 3).move_to(VGroup(square_a, square_b)), run_time=2 ) # 场景3:图形重组动画 # 切割正方形为三角形 triangles = VGroup() for square in [square_a, square_b]: points = square.get_vertices() tri1 = Polygon(points[0], points[1], points[3], color=RED if square == square_a else BLUE) tri2 = Polygon(points[1], points[2], points[3], color=RED if square == square_a else BLUE) triangles.add(tri1, tri2) # 动画重组 self.play(LaggedStart(*[tri.animate.rotate(PI / 2).shift(UR * 2) for tri in triangles]), run_time=3, rate_func=smooth) # 拼合新正方形 new_square = Square(color=GREEN).surround(triangles) self.play(Transform(VGroup(triangles), new_square), run_time=2) # 场景4:面积等价证明 # 并排对比 original = VGroup(tri.copy(), square_a.copy(), square_b.copy()).scale(0.5).to_edge(LEFT) transformed = VGroup(new_square.copy(), square_c.copy()).scale(0.5).to_edge(RIGHT) self.play( FadeOut(arrows), Transform(VGroup(tri, square_a, square_b), original), Transform(VGroup(triangles, square_c), transformed), run_time=2 ) # 显示等式 final_eq = Tex(r"a^2 + b^2 = c^2", color=YELLOW).scale(2) self.play( Write(final_eq), final_eq.animate.shift(UP * 1.5), self.camera.frame.animate.move_to(final_eq), run_time=2 ) # 粒子特效 self.add(final_eq) self.play( final_eq.animate.scale(1.5).set_color_by_gradient(RED, BLUE, GREEN), rate_func=there_and_back, run_time=3 ) # 三维旋转(需启用ThreeDScene) self.play( final_eq.animate.rotate(30 * DEGREES, axis=UP), run_time=2, rate_func=smooth ) self.wait(3) if __name__ == "__main__": config = { "quality": "high_quality", "preview": True, "media_dir": "./output", "pixel_height": 1080, "pixel_width": 1920, "background_color": "#333333", # 深色背景 "format": "png" # 解决部分系统渲染问题 } with tempconfig(config): scene = PythagoreanProof() scene.render()