场景与分组
clear / remove 的场景语义、VGroup 的下标与嵌套、循环搭建,以及 3D 相机的「正」。
本页 6 条示例。代码引自 corpus/examples/scene/,截图为真机渲染的终态。
clear 后重新画
clear 后画面清空,随后新画的物体单独出现。

py
"""clear 后重新画
@expect clear 后画面清空,随后新画的物体单独出现。"""
from manim import *
class ClearScene(Scene):
def construct(self):
self.add(Circle(radius=1.5))
self.wait(0.2)
self.clear()
self.add(Square(side_length=2))
self.wait(0.2)remove 摘掉物体
被 remove 的物体消失,其余物体原样保留:场景放三个物体,只 remove 其中一个(红圆,标注「remove」),终帧蓝方块与黄三角仍在、红圆不在——「只删一个」自证。

py
"""remove 摘掉物体
@expect 被 remove 的物体消失,其余物体原样保留:场景放三个物体,
只 remove 其中一个(红圆,标注「remove」),终帧蓝方块与黄三角
仍在、红圆不在——「只删一个」自证。
"""
from manim import *
class RemoveScene(Scene):
def construct(self):
square = Square(side_length=1.6, color=BLUE)
square.move_to([-3.5, 0, 0])
circle = Circle(radius=0.9, color=RED)
circle.move_to([0, 0, 0])
triangle = Triangle(color=YELLOW)
triangle.move_to([3.5, 0, 0])
self.play(Create(square), Create(circle), Create(triangle))
gone = Text("remove", font_size=24, color=RED)
gone.move_to([0, 1.6, 0])
stay = Text("保留", font_size=24, color=GREY_A)
stay.move_to([-3.5, 1.6, 0])
stay2 = Text("保留", font_size=24, color=GREY_A)
stay2.move_to([3.5, 1.6, 0])
self.play(FadeIn(gone), FadeIn(stay), FadeIn(stay2))
# 只摘红圆一个,其余原样保留
self.remove(circle)
self.wait(0.3)VGroup + 下标取子物体
下标取出的子物体单独被操作,越界下标抛 IndexError(print 断言为准)。

py
"""VGroup + 下标取子物体
@expect 下标取出的子物体单独被操作,越界下标抛 IndexError(print 断言为准)。"""
from manim import *
class VgroupIndexScene(Scene):
def construct(self):
dots = VGroup(*[Dot(point=[i - 2, 0, 0]) for i in range(5)])
self.play(FadeIn(dots))
self.play(dots[0].animate.set_color(RED))
self.wait(0.3)VGroup 套 VGroup
嵌套组整体动、子组也单独动,两层互不串。自证:外层整体上移后红点跟着走,内层再单独变黄、红点颜色不变。

py
"""VGroup 套 VGroup
@expect 嵌套组整体动、子组也单独动,两层互不串。
自证:外层整体上移后红点跟着走,内层再单独变黄、红点颜色不变。"""
from manim import *
class VgroupNestedScene(Scene):
def construct(self):
inner = VGroup(Circle(radius=0.4), Square(side_length=0.6))
inner.arrange(RIGHT, buff=0.3)
outer = VGroup(inner, Dot(point=[0, -1.5, 0], color=RED))
self.play(FadeIn(outer))
# 第一步:外层整体上移——圆、方、红点一起动
self.play(outer.animate.shift(UP * 0.8))
# 第二步:内层单独变色——只有圆和方变黄,红点不动也不变色
self.play(inner.animate.set_color(YELLOW))
note = Text("外层整体上移,内层单独变色", font_size=24).move_to([0, -3.2, 0])
self.play(FadeIn(note))
self.wait(0.3)循环搭一组方块
循环搭出的一排(一列)方块,数量与循环次数一致。

py
"""循环搭一组方块
@expect 循环搭出的一排(一列)方块,数量与循环次数一致。
@note VGroup() 无参构造 + add 累积,是很常见的搭法
"""
from manim import *
class LoopBuildScene(Scene):
def construct(self):
squares = VGroup()
for i in range(4):
sq = Square(side_length=0.8, color=BLUE)
sq.shift(RIGHT * (i * 1.2 - 1.8))
squares.add(sq)
self.play(Create(squares))
self.wait(0.3)3D 相机的「正」:x 轴该在屏幕上水平
五个立方体排成一个正十字:红(x=-4)在左、蓝(x=+4)在右,两者的高低完全一样;黄(y=+3)在上、橙(y=-3)在下,两者与中间绿块的横向位置完全一样。立方体各自露出顶面与正面(有光、有深度)。

py
"""3D 相机的「正」:x 轴该在屏幕上水平
@expect 五个立方体排成一个**正十字**:红(x=-4)在左、蓝(x=+4)在右,两者的高低完全一样;
黄(y=+3)在上、橙(y=-3)在下,两者与中间绿块的横向位置完全一样。
立方体各自露出顶面与正面(有光、有深度)。
@note 这条是「相机没被滚转」的哨兵,因为滚转是**看不出来的错**:相机位置、角度全都对,
`getOrbitAngles()` 读回来分毫不差,只有画面歪——任何几何断言都抓不到它。
2026-10-11 实测:manim-web 0.3.24 的 `Camera3D.orbit` 用 `this._up || (…)` 把「相机朝上」
锁在**第一次**调用上,于是建场景时那组默认角度(phi=70°/theta=-135°)会一直残留——
这里渲出来就是 x 轴的三个立方体**斜着往上**(歪 15°)。修法与出处见
`src/engine/manim-patch.ts`。
"""
from manim import *
class ThreeDUprightScene(ThreeDScene):
def construct(self):
self.set_camera_orientation(phi=50 * DEGREES, theta=-90 * DEGREES) # 正面俯视:x 轴该水平
self.add(
Cube(color=RED).shift([-4, 0, 0]),
Cube(color=GREEN).shift([0, 0, 0]),
Cube(color=BLUE).shift([4, 0, 0]),
Cube(color=YELLOW).shift([0, 3, 0]),
Cube(color=ORANGE).shift([0, -3, 0]),
)