commit be96070dba95747ddbdd53a0e82bd18f4b3d1c0e Author: Tommmy Date: Sun May 18 11:44:53 2025 +0800 上传文件至 / 数学动画们 diff --git a/camera.py b/camera.py new file mode 100644 index 0000000..b4b7d04 --- /dev/null +++ b/camera.py @@ -0,0 +1,29 @@ +from manim import * + +class MoveCameraToCorner(Scene): + def construct(self): + # 创建坐标轴 + axes = Axes( + x_range=[0, 10, 1], + y_range=[0, 10, 1], + x_length=6, + y_length=6, + axis_config={"include_numbers": True}, + ) + self.add(axes) + + # 等待一会儿观察默认位置 + self.wait(1) + + # 将相机移到让原点在左下角的位置,并缩放 + self.camera.frame.save_state() # 保存初始状态(可选) + self.camera.frame.move_to(axes.c2p(5, 5)) # 把坐标系中心移到画面中心 + self.camera.frame.shift(LEFT * 5.5 + DOWN * 3.2) # 向左下移动 + self.camera.frame.scale(0.5) # 缩小画面,相当于放大坐标轴 + + self.wait(1) # 等待动画前静止 + + # 动画执行移动和缩放 + self.play(self.camera.frame.animate.move_to(axes.c2p(5, 5)).shift(LEFT * 5.5 + DOWN * 3.2).scale(0.5), run_time=3) + + self.wait(2) diff --git a/cartasin.py b/cartasin.py new file mode 100644 index 0000000..150a7a4 --- /dev/null +++ b/cartasin.py @@ -0,0 +1,48 @@ +from manim import * +import numpy as np + +class CartesianPlaneScene(Scene): + def construct(self): + # 一、创建坐标平面,先隐藏网格和数字 + plane = NumberPlane( + x_range=[-5, 5, 1], + y_range=[-3, 3, 1], + background_line_style={ + "stroke_color": GREY, + "stroke_width": 1, + "stroke_opacity": 1, + }, + axis_config={ + "include_tip": True, + "tip_length": 0.15, + } + ) + # 生成坐标数字,但先透明 + plane.add_coordinates() + plane.background_lines.set_opacity(0) + plane.coordinate_labels.set_opacity(0) + + # 二、动画绘制 X 轴和 Y 轴 + self.play( + Create(plane.x_axis, run_time=2), + Create(plane.y_axis, run_time=2), + ) + self.wait(1) + + # 三、写出刻度数字 + self.play( + FadeIn(plane.coordinate_labels, shift=DOWN*0.2), + run_time=2 + ) + self.wait(1) + + # 四、绘制网格线 + self.play( + Create(plane.background_lines, run_time=3), + ) + self.wait(1) + + # 五、突出原点 + origin_dot = Dot(plane.c2p(0, 0), color=RED) + self.play(FadeIn(origin_dot), run_time=1) + self.wait(2) diff --git a/simple_scene.py b/simple_scene.py new file mode 100644 index 0000000..933003c --- /dev/null +++ b/simple_scene.py @@ -0,0 +1,54 @@ +from manim import * + +class OpeningManim(Scene): + def construct(self): + title = Tex(r"This is some \LaTeX") + basel = MathTex(r"\sum_{n=1}^\infty \frac{1}{n^2} = \frac{\pi^2}{6}") + VGroup(title, basel).arrange(DOWN) + self.play( + Write(title), + FadeIn(basel, shift=DOWN), + ) + self.wait() + + transform_title = Tex("That was a transform") + transform_title.to_corner(UP + LEFT) + self.play( + Transform(title, transform_title), + LaggedStart(*[FadeOut(obj, shift=DOWN) for obj in basel]), + ) + self.wait() + + grid = NumberPlane() + grid_title = Tex("This is a grid", font_size=72) + grid_title.move_to(transform_title) + + self.add(grid, grid_title) # Make sure title is on top of grid + self.play( + FadeOut(title), + FadeIn(grid_title, shift=UP), + Create(grid, run_time=3, lag_ratio=0.1), + ) + self.wait() + + grid_transform_title = Tex( + r"That was a non-linear function \\ applied to the grid" + ) + grid_transform_title.move_to(grid_title, UL) + grid.prepare_for_nonlinear_transform() + self.play( + grid.animate.apply_function( + lambda p: p + + np.array( + [ + np.sin(p[1]), + np.sin(p[0]), + 0, + ] + ) + ), + run_time=3, + ) + self.wait() + self.play(Transform(grid_title, grid_transform_title)) + self.wait() \ No newline at end of file diff --git a/study.py b/study.py new file mode 100644 index 0000000..6d565d9 --- /dev/null +++ b/study.py @@ -0,0 +1,183 @@ +from manim import * +import math + +class FadeInExample(MovingCameraScene): + def construct(self): + # —— 1. 文本淡入淡出(原样保留)—— # + self.wait(0.5) + tex = Tex("Inverse ", "Proportion ", "Function").scale(1) + self.play(Write(tex), run_time=2) + self.wait(1) + self.play( + AnimationGroup( + FadeOut(tex[0], shift=DOWN), + FadeOut(tex[1], shift=DOWN), + lag_ratio=0.09 + ) + ) + self.play(tex[2].animate.to_corner(UL)) + self.wait(0.3) + + # —— 2. 定义坐标系 & 函数(原样保留)—— # + axes = Axes( + x_range=[-6, 8, 1], + y_range=[-3, 5, 1], + x_length=13, + y_length=6, + axis_config={ + "include_tip": False, + "numbers_to_include": [], + "color": WHITE + } + ).add_coordinates() + labels = axes.get_axis_labels() + func1 = axes.plot(lambda x: 1/x, x_range=[0.1, 11], color=YELLOW) + func2 = axes.plot(lambda x: 1/x, x_range=[-25, -0.1], color=YELLOW) + credits = Tex("Made with Manim by David", font_size=24) + + # —— 3. 播放坐标系 & 函数动画(原样保留)—— # + self.add(credits.to_corner(DR)) + self.play( + Create(axes, run_time=3, lag_ratio=0.1), + Write(credits, run_time=1), + ) + self.add(labels) + self.play(Write(labels)) + self.play(Create(func1, run_time=3), Create(func2, run_time=1)) + + # —— 4. 相机缩放前的公式高亮(原样保留)—— # + equation = MathTex("y", "=", r"\frac{1}{x}") + equation.move_to(UR) + self.play(Write(equation), run_time=1) + self.wait(0.5) + rect = SurroundingRectangle(equation[0], color=YELLOW) + self.play(Create(rect), run_time=0.6) + self.wait(0.5) + new_equation = MathTex(r"f(x)", "=", r"\frac{1}{x}") + new_equation.move_to(equation) + new_rect = SurroundingRectangle(new_equation[0], color=YELLOW) + self.play( + Transform(equation, new_equation), + Transform(rect, new_rect), + run_time=1 + ) + self.play(FadeOut(rect), run_time=0.5) + + # —— 5. 相机移动与缩放(原样保留)—— # + self.camera.frame.save_state() + center = axes.c2p( + (axes.x_range[0] + axes.x_range[1]) / 2, + (axes.y_range[0] + axes.y_range[1]) / 2 + ) + shift_vec = RIGHT * 1.6 + UP * 0.7 + scale_factor = 0.6 + self.play( + self.camera.frame.animate + .move_to(center) + .shift(shift_vec) + .scale(scale_factor), + run_time=1.4 + ) + self.remove(credits) + self.add(credits.to_corner(DR)) + self.play(Write(credits), run_time=1) + + # —— 6. 新增积分区域动画(核心修复)—— # + # ValueTracker 跟踪 x(初始值设为 e) + t = ValueTracker(math.e) + + # dot:始终在 (t, 1/t) 上 + dot = Dot().set_z_index(10) + dot.add_updater(lambda m: m.move_to( + axes.c2p(t.get_value(), 1 / t.get_value()) + )) + + # 动态积分区域 + integral = always_redraw(lambda: axes.get_area( + func1, + x_range=[1, t.get_value()], + color=BLUE, + opacity=0.5 + )) + integral_border = always_redraw(lambda: axes.plot( + lambda x: 1/x, + x_range=[1, t.get_value()], + color=YELLOW, + stroke_width=2 + )) + + # 创建动态文本函数 + def create_text(): + x_val = t.get_value() + area_val = math.log(x_val) + return VGroup( + MathTex(f"x = {x_val:.2f}"), + MathTex(f"A = {area_val:.2f}") + ).arrange(DOWN, aligned_edge=LEFT) + + # 动态文本,并添加 updater + dynamic_text = create_text() + dynamic_text.next_to(dot, UR, buff=0.3) + def update_text(group): + x_val = t.get_value() + area_val = math.log(x_val) + group[0].become(MathTex(f"x = {x_val:.2f}")) + group[1].become(MathTex(f"A = {area_val:.2f}")) + group.arrange(DOWN, aligned_edge=LEFT) + group.next_to(dot, UP + RIGHT * 5, buff=0.3) + dynamic_text.add_updater(update_text) + + # 添加并播放 + self.add(dot, integral, integral_border) + self.play(Create(integral), Create(integral_border), run_time=2) + + # 切换到动态文本 + self.add(dynamic_text) + self.play(Write(dynamic_text), run_time=2) + + # x 在 e±0.5 之间滑动 + self.play(t.animate.set_value(math.e + 0.5), run_time=1) + self.play(t.animate.set_value(math.e - 0.5), run_time=1) + self.play(t.animate.set_value(math.e), run_time=1) + self.wait(1) + + # —— 7. 转换为积分形式并高亮(原样保留)—— # + integral_eq = MathTex( + r"\int_{1}^{x} \frac{1}{x}\,dx = 1" + ).move_to(ORIGIN).shift(RIGHT * 1.3 + UP) + + def highlight(mobj): + return Circumscribe( + mobj, + color=YELLOW, + time_width=2, + run_time=1.5, + fade_out=True + ) + + def sync_hl(): + return ( + highlight(integral_eq[0][5]), # x + highlight(integral_eq[0][-1]), # 1 + highlight(dynamic_text[0][-1]),# 动态 x + highlight(dynamic_text[1][-1]) # 动态 A + ) + + self.play(Transform(equation, integral_eq), run_time=1.5) + self.play(sync_hl(), run_time=2) + + final_eq = MathTex( + r"\int_{1}^{e} \frac{1}{x}\,dx = 1" + ).move_to(integral_eq) + self.play( + Transform(equation, final_eq), + highlight(final_eq[0][5]), + highlight(dynamic_text[0][-1]), + run_time=2 + ) + self.play( + Indicate(final_eq[0][5], color=YELLOW), + Indicate(dynamic_text[0][-1], color=YELLOW), + run_time=1.5 + ) + self.wait(1) diff --git a/study_backup2.py b/study_backup2.py new file mode 100644 index 0000000..0caf884 --- /dev/null +++ b/study_backup2.py @@ -0,0 +1,166 @@ +from manim import * +import math + +class FadeInExample(MovingCameraScene): + def construct(self): + # —— 1. 文本淡入淡出(略) —— # + self.wait(0.5) + tex = Tex("Inverse ", "Proportion ", "Function").scale(1) + self.play(Write(tex), run_time=2) + self.wait(1) + self.play( + AnimationGroup( + FadeOut(tex[0], shift=DOWN), + FadeOut(tex[1], shift=DOWN), + lag_ratio=0.09 + ) + ) + self.play(tex[2].animate.to_corner(UL)) + self.wait(0.3) + + # —— 2. 定义坐标系 & 函数 —— # + axes = Axes( + x_range=[-6, 8, 1], + y_range=[-3, 5, 1], + x_length=13, + y_length=6, + axis_config={ + "include_tip": False, + "numbers_to_include": [], + "color": WHITE + } + ).add_coordinates() + labels = axes.get_axis_labels() + func1 = axes.plot(lambda x: 1/x, x_range=[0.1, 11], color=YELLOW) + func2 = axes.plot(lambda x: 1/x, x_range=[-25, -0.1], color=YELLOW) + credits = Tex("Made with Manim by David", font_size=24) + + # —— 3. 播放坐标系 & 函数动画 —— # + self.add(credits.to_corner(DR)) + self.play( + Create(axes, run_time=3, lag_ratio=0.1), + Write(credits, run_time=1), + ) + self.add(labels) + self.play(Write(labels)) + self.play(Create(func1, run_time=3), Create(func2, run_time=1)) + + # —— 4. 相机缩放前的公式高亮(略) —— # + equation = MathTex("y", "=", r"\frac{1}{x}") + equation.move_to(UR) + self.play(Write(equation), run_time=1) + self.wait(0.5) + rect = SurroundingRectangle(equation[0], color=YELLOW) + self.play(Create(rect), run_time=0.6) + self.wait(0.5) + new_equation = MathTex(r"f(x)", "=", r"\frac{1}{x}") + new_equation.move_to(equation) + new_rect = SurroundingRectangle(new_equation[0], color=YELLOW) + self.play( + Transform(equation, new_equation), + Transform(rect, new_rect), + run_time=1 + ) + self.play(FadeOut(rect), run_time=0.5) + + # —— 5. 相机移动与缩放 —— # + self.camera.frame.save_state() + center = axes.c2p( + (axes.x_range[0] + axes.x_range[1]) / 2, + (axes.y_range[0] + axes.y_range[1]) / 2 + ) + shift_vec = RIGHT * 1.6 + UP * 0.7 + scale_factor = 0.6 + self.play( + self.camera.frame.animate + .move_to(center) + .shift(shift_vec) + .scale(scale_factor), + run_time=1.4 + + ) + self.remove(credits) + self.add(credits.to_corner(DR)) + self.play(Write(credits), run_time=1) + self.wait(0.3) + + # —— 6. 新增积分区域动画 —— # + # ValueTracker 跟踪 x(初始值设为 e) + t = ValueTracker(math.e) + + # 点 updater:始终在 (t, 1/t) 上 + dot = Dot().set_z_index(10) + dot.add_updater(lambda d: d.move_to( + axes.c2p(t.get_value(), 1 / t.get_value()) + )) + + # 动态多边形:积分区域从 x=1 到 current_x + def make_polygon(): + x = t.get_value() + y = 1 / x + # 顶点为 (1,0), (x,0), (x, y), (1, 1) + p0 = axes.c2p(1, 0) + p1 = axes.c2p(x, 0) + p2 = axes.c2p(x, y) + p3 = axes.c2p(1, 1) + poly = Polygon(p0, p1, p2, p3) + poly.set_fill(BLUE, opacity=0.5) + poly.set_stroke(YELLOW, width=2) + return poly + polygon = always_redraw(make_polygon) + + # 实时显示面积(积分面积) + area_text = always_redraw(lambda: MathTex( + rf"x = {t.get_value():.2f}", + rf"\text{{Area}} = \ln(x) = {math.log(t.get_value()):.2f}" + ).arrange(DOWN).scale(0.6).next_to(dot, RIGHT).shift(UP*1.5)) + + # 添加元素到场景 + self.add(dot, polygon) + self.play( + Create(polygon), + run_time = 1.5 + ) + + self.add(area_text) + self.play( + Write(area_text), + run_time = 3 + ) + + # 动画:x 在 e±0.5 之间滑动,最后停在 e + self.play(t.animate.set_value(math.e + 0.5), run_time=1) + self.play(t.animate.set_value(math.e - 0.5), run_time=1) + self.play(t.animate.set_value(math.e), run_time=1) + self.wait(1) + + # —— 7. 转换为积分形式并高亮 x —— # + self.play( + Transform(equation, MathTex( + r"\int_{1}^{x} \frac{1}{t}\,dt = \ln(x)" + ).move_to(RIGHT * 1.3 + UP)), + run_time=1.5 + ) + + # 高亮 x + highlight_rect = SurroundingRectangle(equation[-2][1], color=YELLOW) + self.play(Create(highlight_rect), run_time=0.6) + self.wait(0.5) + + # 将 x 替换为 e + self.play( + Transform(equation, MathTex( + r"\int_{1}^{e} \frac{1}{t}\,dt = 1" + ).move_to(equation)), + run_time=1.5 + ) + self.wait(0.5) + + # 清除并添加 x = e + self.play( + Transform(equation, MathTex("x = e").move_to(equation)), + FadeOut(highlight_rect, shift=DOWN), + FadeOut(area_text, shift=DOWN), # 同时移除面积文本 + run_time=1 + ) + self.wait(1) \ No newline at end of file