因为我是小白,所以我第一次制作效果可能不是太好,生成上述视频的代码如下所示:

from manim import *

# 适配 ManimCE v0.18+
class EuclidEquilateralConstruction(MovingCameraScene):
    def construct(self):
        # ===== 基本参数 =====
        A = LEFT * 3 + DOWN * 1
        B = RIGHT * 3 + DOWN * 1
        color_segment = YELLOW
        color_circleA = BLUE
        color_circleB = GREEN
        color_triangle = RED

        # ===== 标题 =====
        title = Text("欧几里得作图:在给定线段上作等边三角形", font="Noto Sans CJK SC", weight=BOLD).to_edge(UP)
        subtitle = Text("命题 I:给定线段 AB,作等边三角形 ABC", font="Noto Sans CJK SC").next_to(title, DOWN, buff=0.2)
        self.play(FadeIn(title, shift=UP*0.3), FadeIn(subtitle, shift=UP*0.3))
        self.wait(0.5)

        # ===== 给定线段 AB =====
        dotA = Dot(A, color=WHITE)
        dotB = Dot(B, color=WHITE)
        labelA = MathTex("A").next_to(dotA, DOWN)
        labelB = MathTex("B").next_to(dotB, DOWN)
        segAB = Line(A, B, color=color_segment)
        self.play(Create(segAB), FadeIn(dotA), FadeIn(dotB), FadeIn(labelA), FadeIn(labelB))
        self.wait(0.5)

        note1 = Text("已知线段 AB", font="Noto Sans CJK SC").scale(0.6).to_edge(DOWN)
        self.play(Write(note1))
        self.wait(0.5)

        # ===== 以 A 为圆心、AB 为半径作圆 =====
        circleA = Circle(radius=segAB.get_length(), color=color_circleA).move_to(A)
        braceA = BraceBetweenPoints(A, B, direction=UP)
        braceA_text = braceA.get_tex("AB")
        self.play(GrowFromCenter(circleA), FadeIn(braceA), FadeIn(braceA_text))
        self.wait(0.5)

        note2 = Text("以 A 为圆心、AB 为半径作圆", font="Noto Sans CJK SC").scale(0.6).to_edge(DOWN)
        self.play(ReplacementTransform(note1, note2))
        self.wait(0.5)

        # ===== 以 B 为圆心、BA 为半径作圆 =====
        circleB = Circle(radius=segAB.get_length(), color=color_circleB).move_to(B)
        self.play(GrowFromCenter(circleB))
        self.wait(0.5)

        note3 = Text("以 B 为圆心、BA 为半径作圆", font="Noto Sans CJK SC").scale(0.6).to_edge(DOWN)
        self.play(ReplacementTransform(note2, note3))
        self.wait(0.5)

        # ===== 两圆交点 C(取上方交点)=====
        # 解析几何求交点(上方)
        # 圆心分别为 A(x1,y1), B(x2,y2),半径相等 r = |AB|
        # 两圆连线的中垂线上,交点到中点的距离 h = sqrt(r^2 - (d/2)^2)
        A_np = A
        B_np = B
        mid = (A_np + B_np) / 2
        d = np.linalg.norm(B_np - A_np)
        r = d
        # 单位法向向量(垂直于 AB,指向上方)
        dir_vec = B_np - A_np
        perp = np.array([-dir_vec[1], dir_vec[0], 0.0])
        perp = perp / np.linalg.norm(perp)
        h = np.sqrt(max(r**2 - (d/2)**2, 0))
        C = mid + h * perp  # 上方交点

        dotC = Dot(C, color=WHITE)
        labelC = MathTex("C").next_to(dotC, UP*0.6)
        self.play(FadeIn(dotC, scale=0.8), FadeIn(labelC))
        self.wait(0.5)

        note4 = Text("两圆交于点 C", font="Noto Sans CJK SC").scale(0.6).to_edge(DOWN)
        self.play(ReplacementTransform(note3, note4))
        self.wait(0.5)

        # ===== 连接 AC、BC 得等边三角形 =====
        segAC = Line(A, C, color=color_triangle)
        segBC = Line(B, C, color=color_triangle)
        tri = VGroup(segAB.copy(), segAC, segBC)
        self.play(Create(segAC), Create(segBC))
        self.wait(0.5)

        # ===== 高亮等边性质:AB = BC = CA =====
        # 用弧或标注方式表示相等
        mark1 = CurvedDoubleArrow(A + 0.18*(C-A), B + 0.18*(C-B), color=YELLOW, tip_length=0.15)
        mark2 = CurvedDoubleArrow(B + 0.18*(A-B), C + 0.18*(A-C), color=YELLOW, tip_length=0.15)
        mark3 = CurvedDoubleArrow(C + 0.18*(B-C), A + 0.18*(B-A), color=YELLOW, tip_length=0.15)
        eq_text = MathTex("AB = BC = CA", color=YELLOW).scale(1.0).to_edge(LEFT).shift(UP*0.5)

        self.play(Create(mark1), Create(mark2), Create(mark3))
        self.play(FadeIn(eq_text, shift=RIGHT*0.3))
        self.wait(0.5)

        # ===== 解释文字 =====
        reasoning = VGroup(
            Text("理由:", font="Noto Sans CJK SC").scale(0.6),
            Text("C 在以 A 为圆心、AB 为半径的圆上 ⇒ AC = AB;", font="Noto Sans CJK SC").scale(0.6),
            Text("C 也在以 B 为圆心、BA 为半径的圆上 ⇒ BC = BA;", font="Noto Sans CJK SC").scale(0.6),
            Text("而 AB = BA,故 AB = BC = CA。", font="Noto Sans CJK SC").scale(0.6),
        ).arrange(DOWN, aligned_edge=LEFT).to_edge(RIGHT).shift(DOWN*0.5)

        self.play(LaggedStart(*[Write(m) for m in reasoning], lag_ratio=0.2))
        self.wait(1.0)

        # ===== 收尾:淡出圆,只留等边三角形与结论 =====
        self.play(FadeOut(circleA), FadeOut(circleB), FadeOut(braceA), FadeOut(braceA_text), FadeOut(mark1), FadeOut(mark2), FadeOut(mark3), FadeOut(note4))
        final_box = SurroundingRectangle(tri, color=WHITE, buff=0.2)
        conclusion = Text("作图完成:△ABC 为等边三角形", font="Noto Sans CJK SC").to_edge(DOWN)
        self.play(Create(final_box), FadeIn(conclusion))
        self.wait(1.5)

        # 轻微镜头移动以增强传统“定格”效果
        self.play(self.camera.frame.animate.shift(UP*0.1).set_width(self.camera.frame.get_width()*0.98), run_time=1.5)
        self.wait(1.0) ,,上面这些代码如何用manim运行

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注