from manim import * import math class FadeInExample(MovingCameraScene): def construct(self): # —— 1. 文本淡入淡出(原样保留)—— # self.wait(0.5) tex = Tex("Inverse ", "Proportion ", "Function").scale(1) self.play(Write(tex), run_time=2) self.wait(1) self.play( AnimationGroup( FadeOut(tex[0], shift=DOWN), FadeOut(tex[1], shift=DOWN), lag_ratio=0.09 ) ) self.play(tex[2].animate.to_corner(UL)) self.wait(0.3) # —— 2. 定义坐标系 & 函数(原样保留)—— # axes = Axes( x_range=[-6, 8, 1], y_range=[-3, 5, 1], x_length=13, y_length=6, axis_config={ "include_tip": False, "numbers_to_include": [], "color": WHITE } ).add_coordinates() labels = axes.get_axis_labels() func1 = axes.plot(lambda x: 1/x, x_range=[0.1, 11], color=YELLOW) func2 = axes.plot(lambda x: 1/x, x_range=[-25, -0.1], color=YELLOW) credits = Tex("Made with Manim by David", font_size=24) # —— 3. 播放坐标系 & 函数动画(原样保留)—— # self.add(credits.to_corner(DR)) self.play( Create(axes, run_time=3, lag_ratio=0.1), Write(credits, run_time=1), ) self.add(labels) self.play(Write(labels)) self.play(Create(func1, run_time=3), Create(func2, run_time=1)) # —— 4. 相机缩放前的公式高亮(原样保留)—— # equation = MathTex("y", "=", r"\frac{1}{x}") equation.move_to(UR) self.play(Write(equation), run_time=1) self.wait(0.5) rect = SurroundingRectangle(equation[0], color=YELLOW) self.play(Create(rect), run_time=0.6) self.wait(0.5) new_equation = MathTex(r"f(x)", "=", r"\frac{1}{x}") new_equation.move_to(equation) new_rect = SurroundingRectangle(new_equation[0], color=YELLOW) self.play( Transform(equation, new_equation), Transform(rect, new_rect), run_time=1 ) self.play(FadeOut(rect), run_time=0.5) # —— 5. 相机移动与缩放(原样保留)—— # self.camera.frame.save_state() center = axes.c2p( (axes.x_range[0] + axes.x_range[1]) / 2, (axes.y_range[0] + axes.y_range[1]) / 2 ) shift_vec = RIGHT * 1.6 + UP * 0.7 scale_factor = 0.6 self.play( self.camera.frame.animate .move_to(center) .shift(shift_vec) .scale(scale_factor), run_time=1.4 ) self.remove(credits) self.add(credits.to_corner(DR)) self.play(Write(credits), run_time=1) # —— 6. 新增积分区域动画(核心修复)—— # # ValueTracker 跟踪 x(初始值设为 e) t = ValueTracker(math.e) # dot:始终在 (t, 1/t) 上 dot = Dot().set_z_index(10) dot.add_updater(lambda m: m.move_to( axes.c2p(t.get_value(), 1 / t.get_value()) )) # 动态积分区域 integral = always_redraw(lambda: axes.get_area( func1, x_range=[1, t.get_value()], color=BLUE, opacity=0.5 )) integral_border = always_redraw(lambda: axes.plot( lambda x: 1/x, x_range=[1, t.get_value()], color=YELLOW, stroke_width=2 )) # 创建动态文本函数 def create_text(): x_val = t.get_value() area_val = math.log(x_val) return VGroup( MathTex(f"x = {x_val:.2f}"), MathTex(f"A = {area_val:.2f}") ).arrange(DOWN, aligned_edge=LEFT) # 动态文本,并添加 updater dynamic_text = create_text() dynamic_text.next_to(dot, UR, buff=0.3) def update_text(group): x_val = t.get_value() area_val = math.log(x_val) group[0].become(MathTex(f"x = {x_val:.2f}")) group[1].become(MathTex(f"A = {area_val:.2f}")) group.arrange(DOWN, aligned_edge=LEFT) group.next_to(dot, UP + RIGHT * 5, buff=0.3) dynamic_text.add_updater(update_text) # 添加并播放 self.add(dot, integral, integral_border) self.play(Create(integral), Create(integral_border), run_time=2) # 切换到动态文本 self.add(dynamic_text) self.play(Write(dynamic_text), run_time=2) # x 在 e±0.5 之间滑动 self.play(t.animate.set_value(math.e + 0.5), run_time=1) self.play(t.animate.set_value(math.e - 0.5), run_time=1) self.play(t.animate.set_value(math.e), run_time=1) self.wait(1) # —— 7. 转换为积分形式并高亮(原样保留)—— # integral_eq = MathTex( r"\int_{1}^{x} \frac{1}{x}\,dx = 1" ).move_to(ORIGIN).shift(RIGHT * 1.3 + UP) def highlight(mobj): return Circumscribe( mobj, color=YELLOW, time_width=2, run_time=1.5, fade_out=True ) def sync_hl(): return ( highlight(integral_eq[0][5]), # x highlight(integral_eq[0][-1]), # 1 highlight(dynamic_text[0][-1]),# 动态 x highlight(dynamic_text[1][-1]) # 动态 A ) self.play(Transform(equation, integral_eq), run_time=1.5) self.play(sync_hl(), run_time=2) final_eq = MathTex( r"\int_{1}^{e} \frac{1}{x}\,dx = 1" ).move_to(integral_eq) self.play( Transform(equation, final_eq), highlight(final_eq[0][5]), highlight(dynamic_text[0][-1]), run_time=2 ) self.play( Indicate(final_eq[0][5], color=YELLOW), Indicate(dynamic_text[0][-1], color=YELLOW), run_time=1.5 ) self.wait(1)