168 lines
6.2 KiB
Python
168 lines
6.2 KiB
Python
|
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()
|