编辑代码

from manim import *

class WaterDisplacement(Scene):
    def construct(self):
        # 容器参数
        container_width = 5
        container_height = 4
        initial_water_level = 1.5
        cube_size = 1.0

        # 创建容器(透明边框)
        container = Rectangle(
            width=container_width,
            height=container_height,
            stroke_color=BLUE,
            stroke_width=2,
            fill_opacity=0
        ).to_edge(DOWN, buff=0.5)

        # 初始水位(蓝色矩形)
        water = Rectangle(
            width=container_width,
            height=initial_water_level,
            fill_color=BLUE_E,
            fill_opacity=0.6,
            stroke_width=0
        ).move_to(container.get_bottom(), UP)

        # 立方体物体(红色)
        cube = Square(side_length=cube_size)
        cube.set_fill(RED_E, opacity=0.8)
        cube.set_stroke(WHITE, width=1)
        cube.move_to(container.get_top() + UP)

        # 计算水位上升高度
        cube_volume = cube_size ** 3
        container_base = container_width  # 假设容器深度为1单位
        delta_h = cube_volume / container_base
        final_water_level = initial_water_level + delta_h

        # 数学公式说明
        formula = MathTex(r"\text{物体体积} = \text{水位上升体积}").to_edge(UP)
        calculation = MathTex(
            f"{cube_size}^3 = {container_width} \\times {delta_h:.1f}"
        ).next_to(formula, DOWN)

        # 动画序列
        self.play(Create(container))
        self.play(FadeIn(water))
        self.play(Create(cube))
        self.wait(0.5)

        # 物体下落动画
        cube_target = cube.copy().move_to(container.get_bottom() + UP * (cube_size/2 + 0.05))
        
        # 水位上升动画
        water_height_tracker = ValueTracker(initial_water_level)
        water.add_updater(lambda m: m.stretch_to_fit_height(
            water_height_tracker.get_value()
        ).move_to(container.get_bottom(), UP))

        self.play(
            cube.animate.move_to(cube_target),
            water_height_tracker.animate.set_value(final_water_level),
            Write(VGroup(formula, calculation)),
            run_time=2
        )
        
        # 显示上升高度标注
        rise_line = Line(
            container.get_bottom() + UP * initial_water_level,
            container.get_bottom() + UP * final_water_level,
            color=YELLOW
        ).next_to(container, RIGHT)
        rise_label = MathTex(f"\\Delta h = {delta_h:.1f}").next_to(rise_line, RIGHT)

        self.play(Create(rise_line), Write(rise_label))
        self.wait(3)