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)