Examples

Runnable examples for the currently supported feature set. Previews are lazy and only compile when you click Render preview, so opening this page does not trigger a flood of compile requests.

Coverage

Core Objects

  • - Circle, Square, Rectangle, Line, Arrow, Dot, Polygon, RegularPolygon
  • - Text, Tex, MathTex
  • - ImageMobject, SVGMobject
  • - Group and VGroup

Animation Primitives

  • - Create, FadeIn, FadeOut, Write, Unwrite, GrowFromCenter, GrowFromPoint, ShrinkToCenter, Uncreate
  • - Rotate, Shift, MoveTo, Scale, ScaleInPlace
  • - Transform, ReplacementTransform, TransformFromCopy, ClockwiseTransform, CounterclockwiseTransform
  • - MoveToTarget, ApplyMethod, MoveAlongPath, ApplyPointwiseFunction
  • - AnimationGroup, LaggedStart, LaggedStartMap

Scene Features

  • - Camera frame animate, move_camera, zoom_camera
  • - add_fixed_in_frame_mobjects for HUD/static overlays
  • - Updaters via add_updater / clear_updaters
  • - Voiceovers, captions, background audio, image assets
  • - Compilation diagnostics with line and column mapping
Active Section
3D
9 visibleOpen cards when needed
Browse one category at a time instead of loading a long mixed gallery.
3D

3D primitives gallery

Stage several 3D primitives on axes and orbit the camera around them.

from manim import * class ThreeDGalleryScene(ThreeDScene):    def construct(self):        self.set_camera_orientation(phi=70 * DEGREES, theta=-40 * DEGREES, distance=10)         axes = ThreeDAxes(x_length=6, y_length=4, z_length=4)        cube = Cube().set_color(BLUE).shift(LEFT * 2)        sphere = Sphere(radius=0.8).set_color(GREEN)        cylinder = Cylinder(radius=0.45, height=1.8).set_color(YELLOW).shift(RIGHT * 2)         label = Text("Cube   Sphere   Cylinder", font_size=22, color=WHITE).to_edge(DOWN)        self.add_fixed_in_frame_mobjects(label)         self.add(axes, cube, sphere, cylinder, label)        self.play(FadeIn(cube), FadeIn(sphere), FadeIn(cylinder), run_time=1.0)        self.begin_ambient_camera_rotation(rate=0.12)        self.wait(2.4)        self.stop_ambient_camera_rotation()        self.wait(0.4) scene = ThreeDGalleryScene()scene.construct()
3D primitives gallery preview
3D

3D surface wave

Plot a parametric surface and rotate the camera to read its shape.

from manim import *import numpy as np class SurfaceWaveScene(ThreeDScene):    def construct(self):        self.set_camera_orientation(phi=72 * DEGREES, theta=-35 * DEGREES, distance=8.5)         axes = ThreeDAxes(x_length=5, y_length=5, z_length=3)        surface = Surface(            lambda u, v: [u, v, 0.35 * np.sin(2 * u) * np.cos(2 * v)],            u_range=[-1.8, 1.8],            v_range=[-1.8, 1.8],            resolution=(16, 16),            color=BLUE,        )        mesh = SurfaceMesh(surface, color=WHITE, stroke_width=1)         self.add(axes, surface, mesh)        self.move_camera(phi=62 * DEGREES, theta=-15 * DEGREES, distance=7.8, run_time=1.8)        self.wait(1.0) scene = SurfaceWaveScene()scene.construct()
3D surface wave preview
3D

Checkerboard surface fill

Alternate face colors across a sampled surface with set_fill_by_checkerboard.

from manim import *import numpy as np class CheckerboardSurfaceScene(ThreeDScene):    def construct(self):        self.set_camera_orientation(phi=72 * DEGREES, theta=-35 * DEGREES, distance=8.0)         axes = ThreeDAxes(x_length=5, y_length=5, z_length=3)        surface = Surface(            lambda u, v: [u, v, 0.35 * np.sin(2 * u) * np.cos(2 * v)],            u_range=[-1.8, 1.8],            v_range=[-1.8, 1.8],            resolution=(10, 10),        )        surface.set_fill_by_checkerboard(BLUE_D, BLUE_E, opacity=0.95)         self.add(axes, surface)        self.move_camera(phi=60 * DEGREES, theta=-18 * DEGREES, distance=7.4, run_time=1.8)        self.wait(0.6) scene = CheckerboardSurfaceScene()scene.construct()
Checkerboard surface fill preview
3D

3D convex hull study

Wrap a small 3D point cloud with ConvexHull3D and orbit the camera around it.

from manim import * class ConvexHullStudyScene(ThreeDScene):    def construct(self):        self.set_camera_orientation(phi=68 * DEGREES, theta=-38 * DEGREES, distance=8.2)         axes = ThreeDAxes(x_length=5, y_length=5, z_length=4)        a = Dot3D(point=[-1.4, -0.8, -0.6], color=BLUE)        b = Dot3D(point=[1.1, -1.0, 0.4], color=TEAL)        c = Dot3D(point=[0.6, 1.3, -0.5], color=YELLOW)        d = Dot3D(point=[-0.8, 0.9, 1.0], color=ORANGE)        hull = ConvexHull3D(a, b, c, d, color=WHITE, fill_opacity=0.18)         title = Text("ConvexHull3D", font_size=28, color=WHITE).to_edge(UP)        self.add_fixed_in_frame_mobjects(title)        self.add(axes, hull, a, b, c, d, title)        self.begin_ambient_camera_rotation(rate=0.16)        self.wait(2.2)        self.stop_ambient_camera_rotation()        self.wait(0.3) scene = ConvexHullStudyScene()scene.construct()
3D convex hull study preview
3D

ZoomedScene 3D secondary camera

Drive the inset with its own 3D camera orientation so it shows a different perspective of the same scene.

from manim import * class ZoomedThreeDInset(ZoomedScene):    def __init__(self, **kwargs):        ZoomedScene.__init__(            self,            zoom_factor=0.45,            zoomed_display_height=2.3,            zoomed_display_width=3.8,            image_frame_stroke_width=10,            zoomed_camera_config={"default_frame_stroke_width": 3},            **kwargs        )     def construct(self):        self.set_camera_orientation(phi=70 * DEGREES, theta=-35 * DEGREES, distance=8.2)         axes = ThreeDAxes(x_length=5, y_length=5, z_length=4)        cube = Cube().set_color(BLUE).shift(LEFT * 1.5)        sphere = Sphere(radius=0.8).set_color(GREEN).shift(RIGHT * 1.4 + UP * 0.3)        caption = Text("3D inset uses a second camera", font_size=30, color=WHITE).to_edge(UP)        self.add_fixed_in_frame_mobjects(caption)         self.add(axes, cube, sphere, caption)         frame = self.zoomed_camera.frame        frame.move_to(RIGHT * 1.4 + UP * 0.5)        frame.set_color(PURPLE)        self.zoomed_display.display_frame.set_color(RED)        self.zoomed_display.to_corner(UR, buff=0.45)        self.zoomed_camera.set_camera_orientation(            phi=52 * DEGREES,            theta=18 * DEGREES,            distance=7.2,            focal_distance=10,        )         self.activate_zooming()        self.play(self.get_zoomed_display_pop_out_animation(), run_time=0.8)        self.play(            frame.animate.shift(LEFT * 2.2 + DOWN * 0.7).set(theta=-8 * DEGREES),            run_time=1.4,            rate_func=smooth,        )        self.wait(0.4) scene = ZoomedThreeDInset()scene.construct()
ZoomedScene 3D secondary camera preview
3D

In-place animated surface update

Update one surface in place from a ValueTracker-driven wave instead of rebuilding hundreds of separate tiles.

from manim import *import numpy as np class InPlaceSurfaceUpdateScene(ThreeDScene):    def construct(self):        self.set_camera_orientation(phi=72 * DEGREES, theta=-35 * DEGREES, distance=8.2)         phase = ValueTracker(0)        surface = Surface(            lambda u, v: [u, v, 0.3 * np.sin(2.4 * np.sqrt(u * u + v * v))],            u_range=[-2.1, 2.1],            v_range=[-2.1, 2.1],            resolution=(16, 16),            fill_opacity=0.9,            stroke_opacity=0,        )        surface.set_fill_by_value(            BLUE_D, GREEN_D, YELLOW_D, RED_D,            axis="z",            min_value=-0.3,            max_value=0.3,        )         def update_surface(mob, dt):            mob.update_surface(                lambda u, v: [                    u,                    v,                    0.3 * np.sin(2.4 * np.sqrt(u * u + v * v) - phase.get_value()),                ]            )         surface.add_updater(update_surface)         self.add(surface)        self.play(phase.animate.set_value(4.8), run_time=2.6, rate_func=linear)        self.wait(0.3) scene = InPlaceSurfaceUpdateScene()scene.construct()
In-place animated surface update preview
3D

Surface update with mesh overlay

Pair a filled surface with a SurfaceMesh overlay and refresh both from the latest animated geometry.

from manim import *import numpy as np class SurfaceMeshUpdateScene(ThreeDScene):    def construct(self):        self.set_camera_orientation(phi=74 * DEGREES, theta=-30 * DEGREES, distance=8.0)         phase = ValueTracker(0)        surface = Surface(            lambda u, v: [u, v, 0.28 * np.sin(2 * u) * np.cos(2 * v)],            u_range=[-2, 2],            v_range=[-2, 2],            resolution=(14, 14),            fill_opacity=0.88,            stroke_opacity=0,        )        surface.set_fill_by_value(            BLUE_D, TEAL_C, GREEN_D, YELLOW_D,            axis="z",            min_value=-0.28,            max_value=0.28,        )        mesh = SurfaceMesh(surface, color=GREY_B, stroke_width=0.75)         def update_surface(mob, dt):            mob.update_surface(                lambda u, v: [u, v, 0.28 * np.sin(2 * u + phase.get_value()) * np.cos(2 * v - 0.5 * phase.get_value())]            )         def update_mesh(mob, dt):            mob.update_from_surface(surface)         surface.add_updater(update_surface)        mesh.add_updater(update_mesh)         self.add(surface, mesh)        self.play(phase.animate.set_value(PI), run_time=2.4, rate_func=linear)        self.wait(0.3) scene = SurfaceMeshUpdateScene()scene.construct()
Surface update with mesh overlay preview
3D

2x2x2 cube group move / rotate / scale

Move a grouped 2x2x2 cube, rotate it on two 3D axes, then scale and reposition the whole assembly.

from manim import * class RubikCube2x2MotionExample(ThreeDScene):    def construct(self):        self.set_camera_orientation(phi=70 * DEGREES, theta=-36 * DEGREES, distance=8.2)         cubie_size = 0.92        spacing = 0.98        face_offset = cubie_size / 2 + 0.002         def sticker(color, offset, axis):            face = Square(side_length=cubie_size * 0.86)            face.set_fill(color, opacity=1)            face.set_stroke(WHITE, width=0.6, opacity=0.9)            if axis == "x":                face.rotate(PI / 2, axis=UP)            elif axis == "y":                face.rotate(PI / 2, axis=RIGHT)            face.shift(offset)            return face         def make_cubie(coord):            x, y, z = coord            core = Cube(side_length=cubie_size)            core.set_fill("#111827", opacity=1)            core.set_stroke("#111827", width=0, opacity=1)             cubie = VGroup(core)            cubie.add(sticker("#EF4444" if x > 0 else "#FB923C", (RIGHT if x > 0 else LEFT) * face_offset, "x"))            cubie.add(sticker("#F8FAFC" if y > 0 else "#FACC15", (UP if y > 0 else DOWN) * face_offset, "y"))            cubie.add(sticker("#22C55E" if z > 0 else "#3B82F6", (OUT if z > 0 else IN) * face_offset, "z"))            cubie.move_to([x * spacing / 2, y * spacing / 2, z * spacing / 2])            return cubie         cube = VGroup()        for x in (-1, 1):            for y in (-1, 1):                for z in (-1, 1):                    cube.add(make_cubie((x, y, z)))         title = Text("Grouped 3D transforms", font_size=28, color=WHITE).to_edge(UP)        self.add_fixed_in_frame_mobjects(title)        self.add(title, cube)         self.play(cube.animate.shift(LEFT * 1.3 + UP * 0.35), run_time=0.55)        self.play(            Rotate(cube, angle=PI / 4, axis=UP, about_point=cube.get_center()),            Rotate(cube, angle=-PI / 7, axis=RIGHT, about_point=cube.get_center()),            run_time=0.8,        )        self.play(cube.animate.scale(0.82).move_to(RIGHT * 1.6 + DOWN * 0.2), run_time=0.75)        self.wait(0.25) scene = RubikCube2x2MotionExample()scene.construct()
2x2x2 cube group move / rotate / scale preview
3D

Nested 2x2x2 cube hierarchy

Replace one cubie with a half-size 2x2x2 sub-cube and animate the whole parent group to test nested 3D transforms.

from manim import * def solid_cube(side_length, color):    cube = Cube(side_length=side_length)    cube.set_color(color)    cube.set_fill(color, opacity=1)    cube.set_stroke("#0F172A", width=1.2, opacity=1)    return cube class NestedRubikHierarchyScene(ThreeDScene):    def construct(self):        self.set_camera_orientation(phi=70 * DEGREES, theta=-36 * DEGREES, distance=8.2)         cubie_size = 0.92        spacing = 0.98        nested_size = cubie_size * 0.5        nested_spacing = spacing * 0.5         def make_outer_cubie(coord):            palette = {                (-1, -1, -1): "#FB923C",                (-1, -1, 1): "#FACC15",                (-1, 1, -1): "#F87171",                (-1, 1, 1): "#60A5FA",                (1, -1, -1): "#34D399",                (1, -1, 1): "#A78BFA",                (1, 1, -1): "#F472B6",            }            x, y, z = coord            cubie = solid_cube(cubie_size, palette[coord])            cubie.move_to([x * spacing / 2, y * spacing / 2, z * spacing / 2])            return cubie         def make_nested_cluster(center):            nested = VGroup()            mini_palette = ["#E2E8F0", "#F8FAFC", "#BAE6FD", "#BFDBFE", "#A7F3D0", "#FDE68A", "#FDBA74", "#FCA5A5"]            index = 0            for x in (-1, 1):                for y in (-1, 1):                    for z in (-1, 1):                        mini = solid_cube(nested_size, mini_palette[index])                        mini.move_to([x * nested_spacing / 2, y * nested_spacing / 2, z * nested_spacing / 2])                        nested.add(mini)                        index += 1             shell = Cube(side_length=cubie_size)            shell.set_fill("#000000", opacity=0)            shell.set_stroke("#E2E8F0", width=1.4, opacity=0.65)            nested.add(shell)            nested.move_to(center)            return nested         cube = VGroup()        for x in (-1, 1):            for y in (-1, 1):                for z in (-1, 1):                    center = [x * spacing / 2, y * spacing / 2, z * spacing / 2]                    cube.add(make_nested_cluster(center) if (x, y, z) == (1, 1, 1) else make_outer_cubie((x, y, z)))         title = Text("Nested 3D hierarchy", font_size=28, color=WHITE).to_edge(UP)        self.add_fixed_in_frame_mobjects(title)        self.add(title, cube)         self.play(cube.animate.shift(LEFT * 1.25 + UP * 0.3), run_time=0.55)        self.play(            Rotate(cube, angle=PI / 4, axis=UP, about_point=cube.get_center()),            Rotate(cube, angle=-PI / 7, axis=RIGHT, about_point=cube.get_center()),            run_time=0.8,        )        self.play(cube.animate.scale(0.84).move_to(RIGHT * 1.55 + DOWN * 0.2), run_time=0.75)        self.wait(0.25) scene = NestedRubikHierarchyScene()scene.construct()
Nested 2x2x2 cube hierarchy preview