150 lines
4.7 KiB
Python
150 lines
4.7 KiB
Python
from manim import *
|
||
|
||
|
||
class ParabolaLesson(Scene):
|
||
# 坐标常量定义
|
||
LEFT_MARGIN = 3.2
|
||
AXIS_CENTER = LEFT * LEFT_MARGIN
|
||
TITLE_POS = UP * 3.2
|
||
FORMULA_POS = UP * 2.2
|
||
SLIDER_POS = UP * 1.2
|
||
GRAPH_POS = LEFT * LEFT_MARGIN
|
||
|
||
def construct(self):
|
||
self._intro()
|
||
self._discovery()
|
||
self._proof()
|
||
self._practice()
|
||
|
||
def _intro(self):
|
||
# 创建坐标轴
|
||
axes = Axes(
|
||
x_range=[-3, 3, 1],
|
||
y_range=[0, 8, 2],
|
||
axis_config={"color": BLUE},
|
||
tips=False
|
||
).shift(self.GRAPH_POS)
|
||
|
||
# 初始曲线 y=x²
|
||
curve = axes.plot(lambda x: x ** 2, color=YELLOW)
|
||
|
||
# 标题和公式
|
||
title = Tex("$a$是正数,开口向上", color=GREEN).to_edge(self.TITLE_POS)
|
||
formula = MathTex("y = x^2", color=RED).to_edge(self.FORMULA_POS)
|
||
|
||
# 动画序列
|
||
self.play(Create(axes), run_time=1.5)
|
||
self.play(Create(curve), Write(formula), run_time=2)
|
||
self.play(Write(title), run_time=1.5)
|
||
self.wait(1)
|
||
|
||
# 保存对象
|
||
self.axes = axes
|
||
self.curve = curve
|
||
self.formula = formula
|
||
self.title = title
|
||
|
||
def _discovery(self):
|
||
# 创建滑杆数值显示
|
||
a_value = DecimalNumber(1.0, num_decimal_places=1)
|
||
a_text = Tex("$a = $").next_to(a_value, LEFT)
|
||
a_display = VGroup(a_text, a_value).to_edge(self.SLIDER_POS)
|
||
|
||
# 更新公式为 y=ax²
|
||
new_formula = MathTex("y = a x^2", color=RED).to_edge(self.FORMULA_POS)
|
||
self.play(Transform(self.formula, new_formula), FadeIn(a_display))
|
||
|
||
# 创建滑杆
|
||
slider = NumberLine(x_range=[0.5, 2.5], length=4, include_numbers=True)
|
||
slider.to_edge(self.SLIDER_POS).shift(DOWN * 0.6)
|
||
dot = Dot(color=RED).move_to(slider.n2p(1))
|
||
|
||
# 添加滑杆动画
|
||
self.play(Create(slider), Create(dot))
|
||
|
||
# 定义曲线更新函数
|
||
def update_curve(mob):
|
||
a = a_value.get_value()
|
||
new_curve = self.axes.plot(lambda x: a * x ** 2, color=YELLOW)
|
||
mob.become(new_curve)
|
||
|
||
# 设置数值更新器
|
||
self.curve.add_updater(update_curve)
|
||
|
||
# 参数变化动画序列
|
||
a_values = [0.5, 1.0, 2.0]
|
||
for a in a_values:
|
||
self.play(
|
||
a_value.animate.set_value(a),
|
||
dot.animate.move_to(slider.n2p(a)),
|
||
run_time=3
|
||
)
|
||
self.wait(0.5)
|
||
|
||
# 移除更新器
|
||
self.curve.remove_updater(update_curve)
|
||
|
||
# 保持5秒静止帧
|
||
self.wait(5)
|
||
|
||
def _proof(self):
|
||
# 更新标题
|
||
new_title = Tex("$a$是负数,开口向下", color=GREEN).to_edge(self.TITLE_POS)
|
||
self.play(Transform(self.title, new_title))
|
||
|
||
# 更新公式
|
||
new_formula = MathTex("y = a x^2", color=RED).to_edge(self.FORMULA_POS)
|
||
self.play(Transform(self.formula, new_formula))
|
||
|
||
# 创建新的滑杆数值显示
|
||
a_value = DecimalNumber(-0.5, num_decimal_places=1)
|
||
a_text = Tex("$a = $").next_to(a_value, LEFT)
|
||
a_display = VGroup(a_text, a_value).to_edge(self.SLIDER_POS)
|
||
|
||
# 创建新滑杆
|
||
slider = NumberLine(x_range=[-2.5, -0.5], length=4, include_numbers=True)
|
||
slider.to_edge(self.SLIDER_POS).shift(DOWN * 0.6)
|
||
dot = Dot(color=RED).move_to(slider.n2p(-0.5))
|
||
|
||
# 添加滑杆动画
|
||
self.play(FadeIn(a_display), Create(slider), Create(dot))
|
||
|
||
# 定义曲线更新函数
|
||
def update_curve(mob):
|
||
a = a_value.get_value()
|
||
new_curve = self.axes.plot(lambda x: a * x ** 2, color=YELLOW)
|
||
mob.become(new_curve)
|
||
|
||
# 设置数值更新器
|
||
self.curve.add_updater(update_curve)
|
||
|
||
# 参数变化动画序列
|
||
a_values = [-0.5, -1.0, -2.0]
|
||
for a in a_values:
|
||
self.play(
|
||
a_value.animate.set_value(a),
|
||
dot.animate.move_to(slider.n2p(a)),
|
||
run_time=3
|
||
)
|
||
self.wait(0.5)
|
||
|
||
# 移除更新器
|
||
self.curve.remove_updater(update_curve)
|
||
|
||
# 保持5秒静止帧
|
||
self.wait(5)
|
||
|
||
def _practice(self):
|
||
# 练习环节留空
|
||
pass
|
||
|
||
|
||
if __name__ == "__main__":
|
||
# 全局指定 ctex 模板(一次性)
|
||
config.tex_template = TexTemplateLibrary.ctex
|
||
# 使用临时配置渲染场景(配置只在with块内有效)
|
||
with tempconfig({"preview": True, "quality": "high_quality"}):
|
||
# 实例化场景类
|
||
scene = ParabolaLesson()
|
||
# 执行渲染流程(包含文件生成和预览)
|
||
scene.render() |