from manim import * class ParabolaLesson(Scene): # 坐标常量定义 LEFT_MARGIN = 3.2 AXIS_RANGE = [-4, 4, -1, 3] # 颜色定义 BG_COLOR = "#F5F5F5" CURVE_COLOR = "#00BFFF" FOCUS_COLOR = "#FF4500" DIRECTRIX_COLOR = "#AAAAAA" def construct(self): self.camera.background_color = self.BG_COLOR self._intro() self._discovery() self._proof() self._practice() def _intro(self): # 创建坐标系 axes = Axes( x_range=[-4, 4, 1], y_range=[-1, 3, 1], axis_config={"color": BLACK}, tips=False ) axes_labels = axes.get_axis_labels(x_label="x", y_label="y") # 初始抛物线 (a=1) a_value = ValueTracker(1) parabola = always_redraw(lambda: axes.plot( lambda x: a_value.get_value() * x ** 2, color=self.CURVE_COLOR )) # 添加所有元素 self.add(axes, axes_labels, parabola) def _discovery(self): # 标题 title = Tex("$a$是正数,开口向上", color=BLUE).to_edge(UP) # 公式 formula = MathTex("y = a x^2", color=BLACK).next_to(title, DOWN) # 滑杆 slider = NumberLine( x_range=[0, 2, 0.5], length=4, color=BLACK, include_numbers=True ).to_edge(DOWN) slider_label = Tex("$a$值:", color=BLACK).next_to(slider, LEFT) # 滑杆指示器 dot = Dot(color=RED).move_to(slider.n2p(1)) a_value = ValueTracker(1) dot.add_updater(lambda d: d.move_to(slider.n2p( a_value.get_value() ))) a_text = always_redraw(lambda: DecimalNumber( a_value.get_value(), color=RED ).next_to(dot, UP)) # 添加元素 self.play( Write(title), Write(formula), Create(slider), Write(slider_label) ) self.add(dot, a_text) # 动画:a值变化 (0.5 -> 1 -> 2) self.play( a_value.animate.set_value(0.5), run_time=5, rate_func=rate_functions.ease_in_out_sine ) self.play( a_value.animate.set_value(1), run_time=5, rate_func=rate_functions.ease_in_out_sine ) self.play( a_value.animate.set_value(2), run_time=5, rate_func=rate_functions.ease_in_out_sine ) # 5秒静止帧 self.wait(5) def _proof(self): # 更新标题 new_title = Tex("$a$是负数,开口向下", color=BLUE).to_edge(UP) # 滑杆范围变为负数 slider = NumberLine( x_range=[-2, 0, 0.5], length=4, color=BLACK, include_numbers=True ).to_edge(DOWN) slider_label = Tex("$a$值:", color=BLACK).next_to(slider, LEFT) # 更新滑杆指示器 a_value = ValueTracker(-1) dot = Dot(color=RED).move_to(slider.n2p(-1)) dot.add_updater(lambda d: d.move_to(slider.n2p( a_value.get_value() ))) a_text = always_redraw(lambda: DecimalNumber( a_value.get_value(), color=RED ).next_to(dot, UP)) # 更新公式 formula = MathTex("y = a x^2", color=BLACK).next_to(new_title, DOWN) # 焦点和准线 focus = always_redraw(lambda: Dot( color=self.FOCUS_COLOR ).move_to([0, 1 / (4 * a_value.get_value()), 0])) directrix = always_redraw(lambda: DashedLine( start=[-4, -1 / (4 * a_value.get_value()), 0], end=[4, -1 / (4 * a_value.get_value()), 0], color=self.DIRECTRIX_COLOR )) # 切换元素 self.play( Transform(self.mobjects[0], new_title), Transform(self.mobjects[1], formula), Transform(self.mobjects[2], slider), Transform(self.mobjects[3], slider_label) ) self.add(focus, directrix) # 动画:a值变化 (-0.5 -> -1 -> -2) self.play( a_value.animate.set_value(-0.5), run_time=5, rate_func=rate_functions.ease_in_out_sine ) self.play( a_value.animate.set_value(-1), run_time=5, rate_func=rate_functions.ease_in_out_sine ) self.play( a_value.animate.set_value(-2), run_time=5, rate_func=rate_functions.ease_in_out_sine ) # 5秒静止帧 self.wait(5) def _practice(self): # 添加练习题文本 practice = Tex( "思考题:当$a=-1$时,\\\\焦点和准线在哪里?", color=BLUE ).scale(0.8).to_edge(DOWN) # 显示练习题 self.play(Write(practice)) self.wait(5) if __name__ == "__main__": # 全局指定 ctex 模板(一次性) config.tex_template = TexTemplateLibrary.ctex # 使用临时配置渲染场景(配置只在with块内有效) with tempconfig({ "quality": "low_quality", "preview": True, "output_file": "ParabolaLesson" }): # 实例化场景类 scene = ParabolaLesson() # 执行渲染流程(包含文件生成和预览) scene.render()