使用 GPT + Manim 生成动画的体验非常好。

应该是提示词还不够详细,生成的内容还需要人工微调一下,但是大体结构是非常好的,只需要稍微花费一点力气就可以调整好。

我希望用几何的方式展示平方公式,提示词:

请你使用 Manim 库为我实现下面的动画,它演示了如何用几何的方式表示 (a + b) 的平方 = a 的平方 + b 的平方 + 2 ab。我希望最后展现的效果是这样:
原始正方形(被涂色成4种) = 小正方形a + 2 ab 的长方形 + 小正方形b
他们中线位于同一个水平线上,以达到美观平衡的效果。他们使用 =、+相连接。

class MyManim(Scene):
  def construct(self):
    // draw a square

    // split the square into four parts, 2 smaller squares, 2 rectangles.
    // color the four parts with different color
    // squares width are a and b. draw a and b too.

    // decompose the four part, seperate them a little bit

    // duplicate the four parts, group the duplicated 4 parts into 3 groups:
    //  group 1: square with width a
    //  group 2: square with width b
    //  group 3: two rectanges with width a x b. keep the relative location for the two rectangles unchanged.

最终,通过稍微的调整,输入了如下代码,效果非常棒。可以在 playground 跑跑看:

%%manim -qm SquareOfSum
from manim import *

class SquareOfSum(Scene):
    def construct(self):
        # 定义 a 和 b 的比例
        a = 2
        b = 1
        total = a + b

        # 颜色配置
        color_a2 = BLUE
        color_b2 = GREEN
        color_ab1 = ORANGE
        color_ab2 = YELLOW

        # 创建四个小块(用于大正方形)
        square_a = Square(side_length=a, fill_opacity=0.9, fill_color=color_a2).set_stroke(BLACK)
        rect_ab1 = Rectangle(width=b, height=a, fill_opacity=0.9, fill_color=color_ab1).set_stroke(BLACK)
        rect_ab2 = Rectangle(width=a, height=b, fill_opacity=0.9, fill_color=color_ab2).set_stroke(BLACK)
        square_b = Square(side_length=b, fill_opacity=0.9, fill_color=color_b2).set_stroke(BLACK)
        
        # 组成大正方形
        group_square = VGroup(square_a, rect_ab1, rect_ab2, square_b)
        square_a.move_to(ORIGIN)
        rect_ab1.next_to(square_a, RIGHT, buff=0)
        rect_ab2.next_to(square_a, UP, buff=0)
        square_b.next_to(rect_ab2, RIGHT, buff=0)

        # 边框和标签
        big_border = Square(side_length=total, color=WHITE).move_to(group_square)
        label_total = MathTex("(a + b)^2").next_to(big_border, DOWN)

        # 显示大正方形
        self.play(Create(big_border))
        self.play(FadeIn(group_square))
        self.play(Write(label_total))
        self.wait(1)

        # -----------------------------
        # 添加左侧大括号 a, b, (a+b)
        # -----------------------------
        # 计算顶点
        top_left = big_border.get_corner(UL)
        bottom_left = big_border.get_corner(DL)

        # “b” 段大括号(上半部分)
        brace_b = BraceBetweenPoints(
            top_left, 
            top_left + DOWN * b,
            direction=LEFT
        )
        label_b = brace_b.get_text("b").scale(0.8)

        # “a” 段大括号(下半部分)
        brace_a = BraceBetweenPoints(
            top_left + DOWN * b, 
            bottom_left,
            direction=LEFT
        )
        label_a = brace_a.get_text("a").scale(0.8)


        self.play(Create(brace_a), Write(label_a))
        self.play(Create(brace_b), Write(label_b))
        self.wait(1.5)

        # 为每个部分标注面积
        label_a2 = MathTex("a^2").move_to(square_a)
        label_b2 = MathTex("b^2").move_to(square_b)
        label_ab1 = MathTex("ab").move_to(rect_ab1)
        label_ab2 = MathTex("ab").move_to(rect_ab2)
        self.play(Write(label_a2), Write(label_b2), Write(label_ab1), Write(label_ab2))
        self.wait(1)

        # -----------------------------
        # 将整个正方形移到左侧
        # -----------------------------
        big_group = VGroup(group_square, label_total, label_a2, label_b2, label_ab1, label_ab2,
                           brace_a, brace_b, label_a, label_b)

        self.play(
            big_group.animate.shift(LEFT * 4),
            FadeOut(big_border),
            run_time=1.5
        )
        self.wait(0.5)

        # -----------------------------
        # 准备右侧分解部分:a², 2ab, b²
        # -----------------------------
        group_a2 = VGroup(square_a.copy(), label_a2.copy())
        group_b2 = VGroup(square_b.copy(), label_b2.copy())

        # 2ab 组:保持两个矩形相对位置
        ab1_copy = rect_ab1.copy()
        ab2_copy = rect_ab2.copy()
        label_ab1_copy = label_ab1.copy()
        label_ab2_copy = label_ab2.copy()
        group_2ab = VGroup(ab1_copy, ab2_copy, label_ab1_copy, label_ab2_copy)
        label_ab1_copy.move_to(ab1_copy)
        label_ab2_copy.move_to(ab2_copy)

        # 对齐三个部分到一条水平线上
        eq_sign = MathTex("=").next_to(big_group, RIGHT, buff=0.7)
        group_a2.next_to(eq_sign, RIGHT, buff=0.5)
        group_2ab.next_to(group_a2, RIGHT, buff=0.6)
        group_b2.next_to(group_2ab, RIGHT, buff=0.6)
        
        # 添加符号
        plus1 = MathTex("+").next_to(group_a2, RIGHT, buff=0.2)
        plus2 = MathTex("+").next_to(group_2ab, RIGHT, buff=0.2)

        # 展示等式排列动画
        self.play(
            FadeIn(eq_sign),
            FadeIn(group_a2),
            FadeIn(group_2ab),
            FadeIn(group_b2),
            FadeIn(plus1),
            FadeIn(plus2),
            run_time=2
        )

        # 居中整体
        all_expr = VGroup(big_group, eq_sign, group_a2, plus1, group_2ab, plus2, group_b2)
        self.play(all_expr.animate.move_to(ORIGIN).scale(0.9))
        self.wait(2)

        # 最终公式淡入
        final_eq = MathTex("(a+b)^2 = a^2 + 2ab + b^2").next_to(all_expr, DOWN)
        self.play(Write(final_eq))
        self.wait(3)
Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐