120 lines
4.0 KiB
Python
120 lines
4.0 KiB
Python
from manim import *
|
||
|
||
|
||
class SineDefinition(Scene):
|
||
def construct(self):
|
||
# 第一部分:标题淡入(2秒)
|
||
title = Text("正弦函数的几何意义", font_size=48, color=BLUE)
|
||
self.play(FadeIn(title, run_time=2))
|
||
self.wait(0.5)
|
||
self.play(FadeOut(title, run_time=0.5))
|
||
|
||
# 第二部分:直角三角形展示(5秒)
|
||
# 创建三角形和标签
|
||
triangle = Polygon(ORIGIN, [3, 0, 0], [3, 2, 0], color=WHITE)
|
||
opposite = Line([3, 0, 0], [3, 2, 0], color=GREEN)
|
||
hypotenuse = Line(ORIGIN, [3, 2, 0], color=RED)
|
||
angle_arc = Arc(radius=0.5, start_angle=0, angle=PI / 3.5, color=YELLOW)
|
||
theta = MathTex(r"\theta", color=YELLOW).next_to(angle_arc, DOWN, buff=0.1)
|
||
|
||
# 添加标签文本
|
||
opposite_label = Text("对边", color=GREEN).next_to(opposite, RIGHT, buff=0.1)
|
||
hypotenuse_label = Text("斜边", color=RED).next_to(hypotenuse, UP, buff=0.2).shift(LEFT * 0.5)
|
||
|
||
# 动画展示
|
||
self.play(Create(triangle), run_time=1)
|
||
self.play(Create(angle_arc), Write(theta), run_time=1)
|
||
self.play(Create(opposite), Write(opposite_label), run_time=1.5)
|
||
self.play(Create(hypotenuse), Write(hypotenuse_label), run_time=1.5)
|
||
self.wait(0.5)
|
||
|
||
# 第三部分:单位圆动态演示(8秒)
|
||
# 创建坐标系
|
||
axes = Axes(
|
||
x_range=[-1.5, 1.5],
|
||
y_range=[-1.5, 1.5],
|
||
axis_config={"color": BLUE},
|
||
x_length=5,
|
||
y_length=5
|
||
)
|
||
axes_labels = axes.get_axis_labels(
|
||
x_label=Text("角度 θ", font_size=32),
|
||
y_label=Text("正弦值", font_size=32)
|
||
)
|
||
|
||
# 创建单位圆
|
||
unit_circle = Circle(radius=1, color=WHITE)
|
||
radius_vector = Line(ORIGIN, [1, 0, 0], color=RED)
|
||
|
||
# 创建正弦曲线坐标系
|
||
sin_axes = Axes(
|
||
x_range=[0, 2 * PI, PI / 2],
|
||
y_range=[-1, 1, 0.5],
|
||
x_length=5,
|
||
y_length=3,
|
||
axis_config={"color": BLUE}
|
||
).to_edge(RIGHT)
|
||
sin_axes_labels = sin_axes.get_axis_labels(
|
||
x_label=Text("角度 θ", font_size=32),
|
||
y_label=Text("正弦值", font_size=32)
|
||
)
|
||
|
||
# 动画转换
|
||
self.play(
|
||
ReplacementTransform(triangle, unit_circle),
|
||
ReplacementTransform(hypotenuse, radius_vector),
|
||
FadeOut(opposite),
|
||
FadeOut(angle_arc),
|
||
FadeOut(theta),
|
||
FadeOut(opposite_label),
|
||
FadeOut(hypotenuse_label),
|
||
run_time=2
|
||
)
|
||
self.play(
|
||
Create(axes),
|
||
Create(sin_axes),
|
||
Write(axes_labels),
|
||
Write(sin_axes_labels),
|
||
run_time=2
|
||
)
|
||
|
||
# 动态轨迹
|
||
dot = Dot(color=YELLOW)
|
||
sin_dot = Dot(color=YELLOW)
|
||
trace = TracedPath(dot.get_center, stroke_color=YELLOW, stroke_width=4)
|
||
|
||
# 更新函数
|
||
def update_dot(mob, alpha):
|
||
angle = alpha * 2 * PI
|
||
x = np.cos(angle)
|
||
y = np.sin(angle)
|
||
mob.move_to(axes.c2p(x, y))
|
||
|
||
sin_x = alpha * 2 * PI
|
||
sin_y = np.sin(angle)
|
||
sin_dot.move_to(sin_axes.c2p(sin_x, sin_y))
|
||
return mob
|
||
|
||
# 运行动画
|
||
self.add(trace, dot, sin_dot)
|
||
self.play(
|
||
UpdateFromAlphaFunc(dot, update_dot),
|
||
rate_func=linear,
|
||
run_time=8
|
||
)
|
||
self.remove(trace, dot, sin_dot)
|
||
|
||
# 第四部分:总结公式(3秒)
|
||
formula = MathTex(r"\sin\theta = \frac{\text{对边}}{\text{斜边}}", font_size=60)
|
||
formula.set_color_by_tex("对边", GREEN)
|
||
formula.set_color_by_tex("斜边", RED)
|
||
self.play(Write(formula), run_time=2)
|
||
self.wait(1)
|
||
|
||
# 末尾静止帧(3秒)
|
||
self.wait(3)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
scene = SineDefinition()
|
||
scene.render() |