from manim import * import numpy as np import sys # 确保中文显示正常 print("设置UTF-8编码以支持中文显示") sys.stdout.reconfigure(encoding='utf-8') sys.stderr.reconfigure(encoding='utf-8') class AnimatedFunctionPlot(Scene): def construct(self): print("=== 开始构建动画场景 ===") # 添加片头 print("0. 显示片头:东师理想数学动画AI制作平台作品") title = Text("东师理想数学动画AI制作平台作品", font_size=60, color=WHITE) subtitle = Text("正弦和余弦关系动画演示", font_size=36, color=BLUE).next_to(title, DOWN, buff=0.5) # 淡入标题和副标题 self.play(FadeIn(title, run_time=2)) self.play(FadeIn(subtitle, run_time=1.5)) # 等待2秒 self.wait(2) # 淡出标题和副标题 self.play(FadeOut(title), FadeOut(subtitle), run_time=1.5) # 创建坐标系(修正数学符号显示) print("1. 创建坐标系:范围从-3.5π到3.5π,步长为π/2,y轴范围从-1.5到1.5") axes = Axes( x_range=[-3.5 * PI, 3.5 * PI, PI / 2], y_range=[-1.5, 1.5, 0.5], axis_config={"color": BLUE}, x_axis_config={ # 清空要显示的数字列表 "numbers_to_include": [], "numbers_with_elongated_ticks": np.arange(-3 * PI, 3.5 * PI, PI), "decimal_number_config": { "num_decimal_places": 0, "include_sign": True, }, # 禁用默认数字标签 "include_numbers": False, }, y_axis_config={ "decimal_number_config": { "num_decimal_places": 1, } }, tips=False, ).scale(0.9) # 修正1:使用MathTex并正确转义π符号 print("2. 添加x轴标签:使用MathTex正确显示π符号") x_labels = VGroup(*[ MathTex(r"%d\pi" % i if i != 0 else "0").scale(0.7).move_to(axes.c2p(i * PI, 0)) for i in range(-3, 4) ]) print("3. 播放创建坐标系和标签的动画,持续2秒") self.play( Create(axes, run_time=2), LaggedStart(*[Write(label) for label in x_labels], lag_ratio=0.3), ) self.wait(0.5) # 修正2:使用MathTex包装数学公式 print("4. 绘制正弦函数图像:使用绿色表示sin(x)") sin_graph = axes.plot(lambda x: np.sin(x), color=GREEN) sin_label = axes.get_graph_label( sin_graph, MathTex(r"\sin(x)", color=GREEN), # 使用MathTex替代Tex x_val=-3 * PI, direction=UP ) print("5. 播放绘制正弦曲线和标签的动画,持续3秒") self.play( Create(sin_graph, run_time=3), Write(sin_label, run_time=1), rate_func=linear ) self.wait() # 修正3:余弦公式同样使用MathTex print("6. 绘制余弦函数图像:使用红色表示cos(x)") cos_graph = axes.plot(lambda x: np.cos(x), color=RED) cos_label = axes.get_graph_label( cos_graph, MathTex(r"\cos(x)", color=RED), # 使用MathTex替代Tex x_val=3 * PI, direction=DOWN ) print("7. 播放从正弦曲线变换到余弦曲线的动画,持续3秒") self.play( TransformFromCopy(sin_graph, cos_graph, path_arc=PI / 2, run_time=3), FadeIn(cos_label, shift=DOWN), ) self.wait() # 动态垂直线(追踪动画) print("8. 创建动态垂直线和跟踪点:用于展示任意x值对应的sin和cos函数值") tracker = ValueTracker(-3 * PI) vert_line = always_redraw(lambda: DashedLine( axes.c2p(tracker.get_value(), -1.5), axes.c2p(tracker.get_value(), 1.5), color=YELLOW ) ) dot_sin = always_redraw(lambda: Dot(color=GREEN).move_to(axes.i2gp(tracker.get_value(), sin_graph)) ) dot_cos = always_redraw(lambda: Dot(color=RED).move_to(axes.i2gp(tracker.get_value(), cos_graph)) ) print("9. 播放创建垂直线和跟踪点的动画") self.play( Create(vert_line), GrowFromCenter(dot_sin), GrowFromCenter(dot_cos) ) print("10. 播放垂直线从-3π移动到3π的动画,持续6秒,展示函数值随x变化") self.play( tracker.animate.set_value(3 * PI), run_time=6, rate_func=linear ) self.wait() # 修正4:相位差公式使用正确数学环境 print("11. 展示相位差公式:cos(x) = sin(x + π/2)") equation = MathTex( r"\cos(x) = \sin\left(x + \frac{\pi}{2}\right)", # 使用MathTex color=YELLOW ).to_edge(UP) print("12. 播放写入公式和移动正弦曲线的动画,持续2秒") self.play( Write(equation), sin_graph.animate.shift(LEFT * PI / 2).set_color(ORANGE), run_time=2 ) print("13. 等待2秒,让观众理解相位差概念") self.wait(2) print("\n=== 动画场景构建完成 ===") if __name__ == '__main__': print("设置渲染配置:高质量、预览模式、输出目录为./output") config = { "quality": "high_quality", "preview": True, "media_dir": "./output", "pixel_height": 1080, "pixel_width": 1920, "background_color": "#1E1E1E" } print("使用临时配置渲染场景") with tempconfig(config): scene = AnimatedFunctionPlot() scene.render()