MathViz Tutorials

Learn from Zero to Hero -- 15 hands-on lessons

Learn MathViz Step by Step

Follow these 15 tutorials from Hello Circle to advanced 3D animations. Each lesson shows the .mviz source alongside the compiled Python output, plus a rendered video preview. Save any example to a .mviz file and run: mathviz compile example.mviz

Step 0 / 15
Beginner

Fundamentals

Master the basics: shapes, text, animations, and positioning.

1

Hello Circle

What you will learn

  • The scene keyword defines a Manim Scene class
  • fn construct(self) is the entry point for every animation
  • Create() draws a shape, FadeOut() removes it
  • .animate enables smooth property transitions
// Tutorial 01: Hello Circle
// Your very first MathViz animation

scene HelloCircle {
    fn construct(self) {
        let circle = Circle()
        circle.set_color(BLUE)
        circle.set_fill(BLUE, opacity: 0.5)
        self.play(Create(circle))
        self.wait(1)

        // Animate the circle changing color
        self.play(circle.animate.set_color(YELLOW))
        self.wait(0.5)

        // Scale it up
        self.play(circle.animate.scale(2))
        self.wait(0.5)

        // Fade it out
        self.play(FadeOut(circle))
    }
}
from manim import *

class HelloCircle(Scene):
    def construct(self):
        circle = Circle()
        circle.set_color(BLUE)
        circle.set_fill(BLUE, opacity=0.5)
        self.play(Create(circle))
        self.wait(1)
        self.play(circle.animate.set_color(YELLOW))
        self.wait(0.5)
        self.play(circle.animate.scale(2))
        self.wait(0.5)
        self.play(FadeOut(circle))
2

Basic Shapes

What you will learn

  • Circle, Square, and Triangle create geometric shapes
  • Named parameters use colon syntax: radius: 0.8
  • shift() moves objects by a direction vector
  • Multiple animations can be played simultaneously
// Tutorial 02: Basic Shapes
// Create circles, squares, triangles, and stars

scene BasicShapes {
    fn construct(self) {
        let circle = Circle(radius: 0.8, color: BLUE)
        let square = Square(side_length: 1.5, color: RED)
        let triangle = Triangle(color: GREEN)
        triangle.scale(1.2)

        circle.shift(LEFT * 3)
        triangle.shift(RIGHT * 3)

        self.play(Create(circle))
        self.play(Create(square))
        self.play(Create(triangle))
        self.wait(0.5)

        let l1 = Text("Circle", color: BLUE)
        l1.scale(0.5)
        l1.next_to(circle, DOWN)
        let l2 = Text("Square", color: RED)
        l2.scale(0.5)
        l2.next_to(square, DOWN)
        let l3 = Text("Triangle", color: GREEN)
        l3.scale(0.5)
        l3.next_to(triangle, DOWN)

        self.play(Write(l1), Write(l2), Write(l3))
        self.wait(1)
        self.play(FadeOut(circle), FadeOut(square), FadeOut(triangle))
        self.play(FadeOut(l1), FadeOut(l2), FadeOut(l3))
    }
}
from manim import *

class BasicShapes(Scene):
    def construct(self):
        circle = Circle(radius=0.8, color=BLUE)
        square = Square(side_length=1.5, color=RED)
        triangle = Triangle(color=GREEN)
        triangle.scale(1.2)
        circle.shift((LEFT * 3))
        triangle.shift((RIGHT * 3))
        self.play(Create(circle))
        self.play(Create(square))
        self.play(Create(triangle))
        self.wait(0.5)
        l1 = Text('Circle', color=BLUE)
        l1.scale(0.5)
        l1.next_to(circle, DOWN)
        l2 = Text('Square', color=RED)
        l2.scale(0.5)
        l2.next_to(square, DOWN)
        l3 = Text('Triangle', color=GREEN)
        l3.scale(0.5)
        l3.next_to(triangle, DOWN)
        self.play(Write(l1), Write(l2), Write(l3))
        self.wait(1)
        self.play(FadeOut(circle), FadeOut(square), FadeOut(triangle))
        self.play(FadeOut(l1), FadeOut(l2), FadeOut(l3))
3

Fade Animations

What you will learn

  • FadeIn and FadeOut for smooth appearance/disappearance
  • Directional fades with shift: parameter
  • FadeTransform morphs one object into another with a fade effect
  • Combining fill color and opacity
// Tutorial 03: Fade Animations
// FadeIn, FadeOut, and various fade effects

scene FadeAnimations {
    fn construct(self) {
        let title = Text("Fade Animations", color: BLUE)
        title.to_edge(UP)
        self.play(Write(title))

        // FadeIn - object appears gradually
        let circle = Circle(radius: 1.0, color: RED)
        circle.set_fill(RED, opacity: 0.5)
        circle.shift(LEFT * 2)
        self.play(FadeIn(circle))
        self.wait(0.5)

        // FadeOut - object disappears gradually
        self.play(FadeOut(circle))
        self.wait(0.5)

        // FadeIn with shift direction
        let square = Square(side_length: 1.5, color: GREEN)
        square.set_fill(GREEN, opacity: 0.5)
        self.play(FadeIn(square, shift: UP))
        self.wait(0.5)

        self.play(FadeOut(square, shift: DOWN))
        self.wait(0.5)

        // FadeTransform morphs one into another
        let obj1 = Circle(radius: 1.0, color: BLUE)
        obj1.set_fill(BLUE, opacity: 0.5)
        self.play(FadeIn(obj1))

        let obj2 = Square(side_length: 2.0, color: YELLOW)
        obj2.set_fill(YELLOW, opacity: 0.5)
        self.play(FadeTransform(obj1, obj2))
        self.wait(1)

        self.play(FadeOut(obj2), FadeOut(title))
    }
}
from manim import *

class FadeAnimations(Scene):
    def construct(self):
        title = Text('Fade Animations', color=BLUE)
        title.to_edge(UP)
        self.play(Write(title))
        circle = Circle(radius=1.0, color=RED)
        circle.set_fill(RED, opacity=0.5)
        circle.shift((LEFT * 2))
        self.play(FadeIn(circle))
        self.wait(0.5)
        self.play(FadeOut(circle))
        self.wait(0.5)
        square = Square(side_length=1.5, color=GREEN)
        square.set_fill(GREEN, opacity=0.5)
        self.play(FadeIn(square, shift=UP))
        self.wait(0.5)
        self.play(FadeOut(square, shift=DOWN))
        self.wait(0.5)
        obj1 = Circle(radius=1.0, color=BLUE)
        obj1.set_fill(BLUE, opacity=0.5)
        self.play(FadeIn(obj1))
        self.wait(0.3)
        obj2 = Square(side_length=2.0, color=YELLOW)
        obj2.set_fill(YELLOW, opacity=0.5)
        self.play(FadeTransform(obj1, obj2))
        self.wait(1)
        self.play(FadeOut(obj2), FadeOut(title))
4

Text Basics

What you will learn

  • Text() creates text objects with optional color
  • Write() animates text being written on screen
  • .animate.set_color() smoothly transitions colors
  • to_edge() positions objects at screen boundaries
// Tutorial 04: Text Basics
// Create text, colored text, and positioned text

scene TextBasics {
    fn construct(self) {
        let hello = Text("Hello, MathViz!")
        hello.scale(1.5)
        self.play(Write(hello))
        self.wait(0.5)
        self.play(FadeOut(hello))

        // Colored text
        let colored = Text("Colors are fun!", color: YELLOW)
        colored.scale(1.2)
        self.play(Write(colored))
        self.wait(0.3)
        self.play(colored.animate.set_color(RED))
        self.wait(0.3)
        self.play(colored.animate.set_color(GREEN))
        self.wait(0.3)
        self.play(FadeOut(colored))

        // Positioned text at all edges
        let t1 = Text("Top", color: BLUE)
        t1.to_edge(UP)
        let t2 = Text("Bottom", color: RED)
        t2.to_edge(DOWN)
        let t3 = Text("Left", color: GREEN)
        t3.to_edge(LEFT)
        let t4 = Text("Right", color: YELLOW)
        t4.to_edge(RIGHT)
        let center = Text("Center", color: WHITE)

        self.play(Write(center))
        self.play(Write(t1), Write(t2), Write(t3), Write(t4))
        self.wait(1)
        self.play(FadeOut(t1), FadeOut(t2), FadeOut(t3), FadeOut(t4), FadeOut(center))
    }
}
from manim import *

class TextBasics(Scene):
    def construct(self):
        hello = Text('Hello, MathViz!')
        hello.scale(1.5)
        self.play(Write(hello))
        self.wait(0.5)
        self.play(FadeOut(hello))
        colored = Text('Colors are fun!', color=YELLOW)
        colored.scale(1.2)
        self.play(Write(colored))
        self.wait(0.3)
        self.play(colored.animate.set_color(RED))
        self.wait(0.3)
        self.play(colored.animate.set_color(GREEN))
        self.wait(0.3)
        self.play(FadeOut(colored))
        t1 = Text('Top', color=BLUE)
        t1.to_edge(UP)
        t2 = Text('Bottom', color=RED)
        t2.to_edge(DOWN)
        t3 = Text('Left', color=GREEN)
        t3.to_edge(LEFT)
        t4 = Text('Right', color=YELLOW)
        t4.to_edge(RIGHT)
        center = Text('Center', color=WHITE)
        self.play(Write(center))
        self.play(Write(t1), Write(t2), Write(t3), Write(t4))
        self.wait(1)
        self.play(FadeOut(t1), FadeOut(t2), FadeOut(t3), FadeOut(t4), FadeOut(center))
5

LaTeX Mathematics

What you will learn

  • MathTex() renders LaTeX mathematical formulas
  • Standard LaTeX notation: \\int, \\frac, ^{}, _{}
  • Scaling and coloring math expressions
  • Famous equations: Einstein, Pythagoras, Euler
// Tutorial 05: LaTeX Mathematics
// Display beautiful mathematical formulas

scene LatexMath {
    fn construct(self) {
        let title = Text("Mathematical Formulas", color: BLUE)
        title.scale(0.8)
        title.to_edge(UP)
        self.play(Write(title))

        // Einstein's equation
        let eq1 = MathTex("E = mc^2")
        eq1.scale(1.5)
        self.play(Write(eq1))
        self.wait(1)
        self.play(FadeOut(eq1))

        // Pythagorean theorem
        let eq2 = MathTex("a^2 + b^2 = c^2")
        eq2.scale(1.5)
        self.play(Write(eq2))
        self.wait(1)
        self.play(FadeOut(eq2))

        // Gaussian integral
        let eq3 = MathTex("\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}")
        eq3.scale(1.2)
        self.play(Write(eq3))
        self.wait(1)
        self.play(FadeOut(eq3))

        // Euler's identity
        let eq4 = MathTex("e^{i\\pi} + 1 = 0")
        eq4.scale(2.0)
        eq4.set_color(YELLOW)
        self.play(Write(eq4))
        self.wait(1.5)
        self.play(FadeOut(eq4), FadeOut(title))
    }
}
from manim import *

class LatexMath(Scene):
    def construct(self):
        title = Text('Mathematical Formulas', color=BLUE)
        title.scale(0.8)
        title.to_edge(UP)
        self.play(Write(title))
        eq1 = MathTex('E = mc^2')
        eq1.scale(1.5)
        self.play(Write(eq1))
        self.wait(1)
        self.play(FadeOut(eq1))
        eq2 = MathTex('a^2 + b^2 = c^2')
        eq2.scale(1.5)
        self.play(Write(eq2))
        self.wait(1)
        self.play(FadeOut(eq2))
        eq3 = MathTex('\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}')
        eq3.scale(1.2)
        self.play(Write(eq3))
        self.wait(1)
        self.play(FadeOut(eq3))
        eq4 = MathTex('e^{i\\pi} + 1 = 0')
        eq4.scale(2.0)
        eq4.set_color(YELLOW)
        self.play(Write(eq4))
        self.wait(1.5)
        self.play(FadeOut(eq4), FadeOut(title))
6

Positioning

What you will learn

  • next_to() places an object relative to another
  • shift() moves by a direction vector (e.g. LEFT * 3)
  • to_edge() and to_corner() for screen placement
  • buff: controls spacing between objects
// Tutorial 06: Positioning
// next_to, shift, to_edge, to_corner

scene Positioning {
    fn construct(self) {
        let center_sq = Square(side_length: 1.0, color: RED)
        center_sq.set_fill(RED, opacity: 0.3)
        self.play(Create(center_sq))

        // next_to places adjacent
        let right_circ = Circle(radius: 0.4, color: BLUE)
        right_circ.next_to(center_sq, RIGHT, buff: 0.3)
        self.play(Create(right_circ))

        let top_circ = Circle(radius: 0.4, color: GREEN)
        top_circ.next_to(center_sq, UP, buff: 0.3)
        self.play(Create(top_circ))
        self.wait(0.5)

        // shift moves by a vector
        let shifted = Square(side_length: 0.6, color: YELLOW)
        shifted.shift(LEFT * 3 + UP * 2)
        self.play(Create(shifted))

        // to_edge places at boundary
        let edge_text = Text("Edge", color: PURPLE)
        edge_text.scale(0.5)
        edge_text.to_edge(DOWN)
        self.play(Write(edge_text))

        // to_corner for corners
        let corner_text = Text("Corner", color: TEAL)
        corner_text.scale(0.5)
        corner_text.to_corner(UL)
        self.play(Write(corner_text))

        self.wait(1)
        self.play(
            FadeOut(center_sq), FadeOut(right_circ), FadeOut(top_circ),
            FadeOut(shifted), FadeOut(edge_text), FadeOut(corner_text)
        )
    }
}
from manim import *

class Positioning(Scene):
    def construct(self):
        center_sq = Square(side_length=1.0, color=RED)
        center_sq.set_fill(RED, opacity=0.3)
        self.play(Create(center_sq))
        right_circ = Circle(radius=0.4, color=BLUE)
        right_circ.next_to(center_sq, RIGHT, buff=0.3)
        self.play(Create(right_circ))
        top_circ = Circle(radius=0.4, color=GREEN)
        top_circ.next_to(center_sq, UP, buff=0.3)
        self.play(Create(top_circ))
        self.wait(0.5)
        shifted = Square(side_length=0.6, color=YELLOW)
        shifted.shift(((LEFT * 3) + (UP * 2)))
        self.play(Create(shifted))
        edge_text = Text('Edge', color=PURPLE)
        edge_text.scale(0.5)
        edge_text.to_edge(DOWN)
        self.play(Write(edge_text))
        corner_text = Text('Corner', color=TEAL)
        corner_text.scale(0.5)
        corner_text.to_corner(UL)
        self.play(Write(corner_text))
        self.wait(1)
        self.play(FadeOut(center_sq), FadeOut(right_circ), FadeOut(top_circ),
            FadeOut(shifted), FadeOut(edge_text), FadeOut(corner_text))
Intermediate

Building Skills

Styling, transforms, graphs, groups, and dynamic updates.

7

Colors & Styling

What you will learn

  • set_color() changes the stroke/border color
  • set_fill(color, opacity:) fills the interior
  • set_stroke(color, width:) controls the border
  • Animate style changes with .animate
// Tutorial 07: Colors and Styling
// set_color, set_fill, set_stroke, opacity

scene ColorsStyling {
    fn construct(self) {
        let title = Text("Colors & Styling", color: BLUE)
        title.scale(0.7)
        title.to_edge(UP)
        self.play(Write(title))

        let c1 = Circle(radius: 0.8)
        c1.set_color(BLUE)
        c1.shift(LEFT * 3)

        let c2 = Circle(radius: 0.8)
        c2.set_fill(RED, opacity: 0.5)
        c2.set_stroke(WHITE, width: 2)

        let c3 = Circle(radius: 0.8)
        c3.set_fill(GREEN, opacity: 0.7)
        c3.set_stroke(YELLOW, width: 4)
        c3.shift(RIGHT * 3)

        self.play(Create(c1), Create(c2), Create(c3))
        self.wait(0.5)

        self.play(c1.animate.set_color(YELLOW))
        self.play(c2.animate.set_fill(BLUE, opacity: 0.8))
        self.wait(1)

        self.play(FadeOut(c1), FadeOut(c2), FadeOut(c3), FadeOut(title))
    }
}
from manim import *

class ColorsStyling(Scene):
    def construct(self):
        title = Text('Colors & Styling', color=BLUE)
        title.scale(0.7)
        title.to_edge(UP)
        self.play(Write(title))
        c1 = Circle(radius=0.8)
        c1.set_color(BLUE)
        c1.shift((LEFT * 3))
        c2 = Circle(radius=0.8)
        c2.set_fill(RED, opacity=0.5)
        c2.set_stroke(WHITE, width=2)
        c3 = Circle(radius=0.8)
        c3.set_fill(GREEN, opacity=0.7)
        c3.set_stroke(YELLOW, width=4)
        c3.shift((RIGHT * 3))
        self.play(Create(c1), Create(c2), Create(c3))
        self.wait(0.5)
        self.play(c1.animate.set_color(YELLOW))
        self.play(c2.animate.set_fill(BLUE, opacity=0.8))
        self.wait(1)
        self.play(FadeOut(c1), FadeOut(c2), FadeOut(c3), FadeOut(title))
8

Transforms

What you will learn

  • Transform(a, b) morphs object a into the shape of b
  • ReplacementTransform(a, b) replaces the reference entirely
  • Chaining with .animate.scale().shift()
  • .animate.rotate(PI / 4) for rotations
// Tutorial 08: Transforms
// Transform, ReplacementTransform, chaining

scene Transforms {
    fn construct(self) {
        let title = Text("Transforms", color: BLUE)
        title.scale(0.7)
        title.to_edge(UP)
        self.play(Write(title))

        let square = Square(side_length: 2.0, color: BLUE)
        square.set_fill(BLUE, opacity: 0.3)
        self.play(Create(square))

        let circle = Circle(radius: 1.0, color: RED)
        circle.set_fill(RED, opacity: 0.3)
        self.play(Transform(square, circle))
        self.wait(0.5)
        self.play(FadeOut(square))

        // ReplacementTransform
        let sq2 = Square(side_length: 1.5, color: GREEN)
        sq2.set_fill(GREEN, opacity: 0.3)
        self.play(Create(sq2))

        let tri = Triangle(color: YELLOW)
        tri.scale(1.5)
        tri.set_fill(YELLOW, opacity: 0.3)
        self.play(ReplacementTransform(sq2, tri))
        self.wait(0.5)

        // Chained animate
        self.play(tri.animate.scale(0.5).shift(UP))
        self.play(tri.animate.rotate(PI / 4))
        self.wait(0.5)
        self.play(FadeOut(tri), FadeOut(title))
    }
}
from manim import *

class Transforms(Scene):
    def construct(self):
        title = Text('Transforms', color=BLUE)
        title.scale(0.7)
        title.to_edge(UP)
        self.play(Write(title))
        square = Square(side_length=2.0, color=BLUE)
        square.set_fill(BLUE, opacity=0.3)
        self.play(Create(square))
        circle = Circle(radius=1.0, color=RED)
        circle.set_fill(RED, opacity=0.3)
        self.play(Transform(square, circle))
        self.wait(0.5)
        self.play(FadeOut(square))
        sq2 = Square(side_length=1.5, color=GREEN)
        sq2.set_fill(GREEN, opacity=0.3)
        self.play(Create(sq2))
        tri = Triangle(color=YELLOW)
        tri.scale(1.5)
        tri.set_fill(YELLOW, opacity=0.3)
        self.play(ReplacementTransform(sq2, tri))
        self.wait(0.5)
        self.play(tri.animate.scale(0.5).shift(UP))
        self.play(tri.animate.rotate((PI / 4)))
        self.wait(0.5)
        self.play(FadeOut(tri), FadeOut(title))
9

Axes & Graphs

What you will learn

  • Axes() creates a coordinate system with configurable ranges
  • axes.plot(|x| sin(x)) uses pipe-lambda syntax for functions
  • Axis labels with get_x_axis_label()
  • Plotting multiple functions on the same axes
// Tutorial 09: Axes and Graphs
// Coordinate axes and function plotting

scene AxesGraphs {
    fn construct(self) {
        let axes = Axes(
            x_range: [-3, 3, 1],
            y_range: [-2, 2, 1],
            axis_config: {"color": BLUE}
        )

        let x_label = axes.get_x_axis_label("x")
        let y_label = axes.get_y_axis_label("y")
        self.play(Create(axes), Write(x_label), Write(y_label))
        self.wait(0.5)

        // Plot sine with pipe-lambda syntax
        let sin_graph = axes.plot(|x| sin(x), color: YELLOW)
        let sin_label = MathTex("\\sin(x)", color: YELLOW)
        sin_label.scale(0.7)
        sin_label.to_corner(UR)
        self.play(Create(sin_graph), Write(sin_label))
        self.wait(0.5)

        // Plot cosine
        let cos_graph = axes.plot(|x| cos(x), color: GREEN)
        let cos_label = MathTex("\\cos(x)", color: GREEN)
        cos_label.scale(0.7)
        cos_label.next_to(sin_label, DOWN)
        self.play(Create(cos_graph), Write(cos_label))
        self.wait(1)

        self.play(
            FadeOut(axes), FadeOut(sin_graph), FadeOut(cos_graph),
            FadeOut(x_label), FadeOut(y_label),
            FadeOut(sin_label), FadeOut(cos_label)
        )
    }
}
from manim import *

class AxesGraphs(Scene):
    def construct(self):
        axes = Axes(x_range=[(-3), 3, 1], y_range=[(-2), 2, 1],
            axis_config={'color': BLUE})
        x_label = axes.get_x_axis_label('x')
        y_label = axes.get_y_axis_label('y')
        self.play(Create(axes), Write(x_label), Write(y_label))
        self.wait(0.5)
        sin_graph = axes.plot(lambda x: np.sin(x), color=YELLOW)
        sin_label = MathTex('\\sin(x)', color=YELLOW)
        sin_label.scale(0.7)
        sin_label.to_corner(UR)
        self.play(Create(sin_graph), Write(sin_label))
        self.wait(0.5)
        cos_graph = axes.plot(lambda x: np.cos(x), color=GREEN)
        cos_label = MathTex('\\cos(x)', color=GREEN)
        cos_label.scale(0.7)
        cos_label.next_to(sin_label, DOWN)
        self.play(Create(cos_graph), Write(cos_label))
        self.wait(1)
        self.play(FadeOut(axes), FadeOut(sin_graph), FadeOut(cos_graph),
            FadeOut(x_label), FadeOut(y_label),
            FadeOut(sin_label), FadeOut(cos_label))
10

Number Plane

What you will learn

  • NumberPlane() creates a full-screen coordinate grid
  • Plotting curves with plane.plot()
  • Dot() creates point markers
  • MoveAlongPath() animates along a curve
// Tutorial 10: Number Plane
// NumberPlane and parametric curves

scene NumberPlaneDemo {
    fn construct(self) {
        let plane = NumberPlane(
            x_range: [-4, 4, 1],
            y_range: [-3, 3, 1],
            background_line_style: {"stroke_opacity": 0.4}
        )
        self.play(Create(plane), run_time: 2)
        self.wait(0.5)

        // Plot a parabola
        let parabola = plane.plot(|x| x * x / 3, color: YELLOW)
        let label = MathTex("f(x) = \\frac{x^2}{3}", color: YELLOW)
        label.scale(0.8)
        label.to_corner(UR)
        self.play(Create(parabola), Write(label))
        self.wait(0.5)

        // Animate a dot along the curve
        let dot = Dot(color: RED)
        dot.move_to(plane.c2p(-3, 3))
        self.play(Create(dot))
        self.play(MoveAlongPath(dot, parabola), run_time: 3)
        self.wait(1)

        self.play(FadeOut(plane), FadeOut(parabola), FadeOut(label), FadeOut(dot))
    }
}
from manim import *

class NumberPlaneDemo(Scene):
    def construct(self):
        plane = NumberPlane(x_range=[(-4), 4, 1], y_range=[(-3), 3, 1],
            background_line_style={'stroke_opacity': 0.4})
        self.play(Create(plane), run_time=2)
        self.wait(0.5)
        parabola = plane.plot(lambda x: ((x * x) / 3), color=YELLOW)
        label = MathTex('f(x) = \\frac{x^2}{3}', color=YELLOW)
        label.scale(0.8)
        label.to_corner(UR)
        self.play(Create(parabola), Write(label))
        self.wait(0.5)
        dot = Dot(color=RED)
        dot.move_to(plane.c2p((-3), 3))
        self.play(Create(dot))
        self.play(MoveAlongPath(dot, parabola), run_time=3)
        self.wait(1)
        self.play(FadeOut(plane), FadeOut(parabola), FadeOut(label), FadeOut(dot))
11

Groups

What you will learn

  • VGroup() groups multiple objects together
  • .arrange(RIGHT, buff: 0.5) lays out objects in a row
  • Animating the entire group at once with group.animate
  • Individual elements remain accessible within the group
// Tutorial 11: Groups
// VGroup, arrange, and batch animations

scene Groups {
    fn construct(self) {
        let title = Text("VGroup & Arrange", color: BLUE)
        title.scale(0.7)
        title.to_edge(UP)
        self.play(Write(title))

        let c1 = Circle(radius: 0.4, color: RED)
        c1.set_fill(RED, opacity: 0.5)
        let c2 = Circle(radius: 0.4, color: GREEN)
        c2.set_fill(GREEN, opacity: 0.5)
        let c3 = Circle(radius: 0.4, color: BLUE)
        c3.set_fill(BLUE, opacity: 0.5)
        let c4 = Circle(radius: 0.4, color: YELLOW)
        c4.set_fill(YELLOW, opacity: 0.5)

        let row = VGroup(c1, c2, c3, c4)
        row.arrange(RIGHT, buff: 0.5)

        self.play(Create(row))
        self.play(row.animate.scale(1.5))
        self.play(row.animate.shift(DOWN))

        let s1 = Square(side_length: 0.6, color: PURPLE)
        s1.set_fill(PURPLE, opacity: 0.5)
        let s2 = Square(side_length: 0.6, color: TEAL)
        s2.set_fill(TEAL, opacity: 0.5)
        let s3 = Square(side_length: 0.6, color: ORANGE)
        s3.set_fill(ORANGE, opacity: 0.5)

        let row2 = VGroup(s1, s2, s3)
        row2.arrange(RIGHT, buff: 0.5)
        row2.next_to(row, UP, buff: 0.8)
        self.play(Create(row2))
        self.wait(1)

        self.play(FadeOut(row), FadeOut(row2), FadeOut(title))
    }
}
from manim import *

class Groups(Scene):
    def construct(self):
        title = Text('VGroup & Arrange', color=BLUE)
        title.scale(0.7)
        title.to_edge(UP)
        self.play(Write(title))
        c1 = Circle(radius=0.4, color=RED)
        c1.set_fill(RED, opacity=0.5)
        c2 = Circle(radius=0.4, color=GREEN)
        c2.set_fill(GREEN, opacity=0.5)
        c3 = Circle(radius=0.4, color=BLUE)
        c3.set_fill(BLUE, opacity=0.5)
        c4 = Circle(radius=0.4, color=YELLOW)
        c4.set_fill(YELLOW, opacity=0.5)
        row = VGroup(c1, c2, c3, c4)
        row.arrange(RIGHT, buff=0.5)
        self.play(Create(row))
        self.play(row.animate.scale(1.5))
        self.play(row.animate.shift(DOWN))
        s1 = Square(side_length=0.6, color=PURPLE)
        s1.set_fill(PURPLE, opacity=0.5)
        s2 = Square(side_length=0.6, color=TEAL)
        s2.set_fill(TEAL, opacity=0.5)
        s3 = Square(side_length=0.6, color=ORANGE)
        s3.set_fill(ORANGE, opacity=0.5)
        row2 = VGroup(s1, s2, s3)
        row2.arrange(RIGHT, buff=0.5)
        row2.next_to(row, UP, buff=0.8)
        self.play(Create(row2))
        self.wait(1)
        self.play(FadeOut(row), FadeOut(row2), FadeOut(title))
12

Updaters

What you will learn

  • ValueTracker() creates an animatable numeric value
  • always_redraw() rebuilds an object every frame
  • Pipe-lambda || creates zero-argument closures
  • Tracking a dot along a plotted curve dynamically
// Tutorial 12: Updaters
// always_redraw and ValueTracker

scene Updaters {
    fn construct(self) {
        let title = Text("Updaters", color: BLUE)
        title.scale(0.7)
        title.to_edge(UP)
        self.play(Write(title))

        // ValueTracker animates a value smoothly
        let tracker = ValueTracker(0)

        // always_redraw rebuilds each frame
        let number = always_redraw(
            || DecimalNumber(tracker.get_value()).scale(1.5).set_color(YELLOW)
        )
        self.play(Create(number))
        self.play(tracker.animate.set_value(10), run_time: 3)
        self.play(FadeOut(number))

        // Dynamic dot tracking along sine
        let t = ValueTracker(-3)
        let axes = Axes(x_range: [-3, 3, 1], y_range: [-2, 2, 1])
        let graph = axes.plot(|x| sin(x), color: YELLOW)
        self.play(Create(axes), Create(graph))

        let dot = always_redraw(
            || Dot(axes.c2p(t.get_value(), sin(t.get_value())), color: RED)
        )
        self.play(Create(dot))
        self.play(t.animate.set_value(3), run_time: 4)
        self.wait(1)

        self.play(FadeOut(axes), FadeOut(graph), FadeOut(dot), FadeOut(title))
    }
}
from manim import *

class Updaters(Scene):
    def construct(self):
        title = Text('Updaters', color=BLUE)
        title.scale(0.7)
        title.to_edge(UP)
        self.play(Write(title))
        tracker = ValueTracker(0)
        number = always_redraw(
            lambda: DecimalNumber(tracker.get_value()).scale(1.5).set_color(YELLOW))
        self.play(Create(number))
        self.play(tracker.animate.set_value(10), run_time=3)
        self.play(FadeOut(number))
        t = ValueTracker((-3))
        axes = Axes(x_range=[(-3), 3, 1], y_range=[(-2), 2, 1])
        graph = axes.plot(lambda x: np.sin(x), color=YELLOW)
        self.play(Create(axes), Create(graph))
        dot = always_redraw(
            lambda: Dot(axes.c2p(t.get_value(), np.sin(t.get_value())), color=RED))
        self.play(Create(dot))
        self.play(t.animate.set_value(3), run_time=4)
        self.wait(1)
        self.play(FadeOut(axes), FadeOut(graph), FadeOut(dot), FadeOut(title))
Advanced

Mastery

3D scenes, theorem visualization, and complex animation orchestration.

13

3D Scenes

What you will learn

  • ThreeDAxes() creates 3D coordinate axes
  • Surface() constructs parametric 3D surfaces
  • set_camera_orientation() for viewing angles
  • begin_ambient_camera_rotation() for orbiting views
// Tutorial 13: 3D Scenes
// ThreeDScene, 3D objects, camera rotation

scene ThreeDDemo {
    fn construct(self) {
        let axes = ThreeDAxes()
        self.play(Create(axes))

        // Create a sphere surface
        let sphere = Surface(
            |u, v| axes.c2p(
                cos(u) * cos(v),
                cos(u) * sin(v),
                sin(u)
            ),
            u_range: [-PI / 2, PI / 2],
            v_range: [0, TAU],
            resolution: (16, 32)
        )
        sphere.set_color(BLUE)
        sphere.set_opacity(0.5)

        self.set_camera_orientation(phi: 70 * DEGREES, theta: -45 * DEGREES)
        self.play(Create(sphere), run_time: 2)

        // Orbit the camera
        self.begin_ambient_camera_rotation(rate: 0.3)
        self.wait(4)
        self.stop_ambient_camera_rotation()

        self.wait(1)
        self.play(FadeOut(axes), FadeOut(sphere))
    }
}
from manim import *

class ThreeDDemo(ThreeDScene):
    def construct(self):
        axes = ThreeDAxes()
        self.play(Create(axes))
        sphere = Surface(
            lambda u, v: axes.c2p(
                np.cos(u) * np.cos(v),
                np.cos(u) * np.sin(v),
                np.sin(u)),
            u_range=[(-PI / 2), (PI / 2)],
            v_range=[0, TAU],
            resolution=(16, 32))
        sphere.set_color(BLUE)
        sphere.set_opacity(0.5)
        self.set_camera_orientation(phi=(70 * DEGREES), theta=((-45) * DEGREES))
        self.play(Create(sphere), run_time=2)
        self.begin_ambient_camera_rotation(rate=0.3)
        self.wait(4)
        self.stop_ambient_camera_rotation()
        self.wait(1)
        self.play(FadeOut(axes), FadeOut(sphere))
14

Complex Math Visualization

What you will learn

  • Visualizing the Fundamental Theorem of Calculus
  • axes.get_area() shades the region under a curve
  • Combining formulas, graphs, and annotations
  • Labeling specific points on axes with axes.c2p()
// Tutorial 14: Complex Math Visualization
// Theorem visualization with formulas and graphs

scene ComplexMath {
    fn construct(self) {
        let title = Text("The Fundamental Theorem of Calculus", color: BLUE)
        title.scale(0.6)
        title.to_edge(UP)
        self.play(Write(title))

        let theorem = MathTex("\\int_a^b f(x)\\,dx = F(b) - F(a)")
        theorem.scale(1.3)
        self.play(Write(theorem))
        self.wait(1)
        self.play(theorem.animate.shift(UP * 0.5).scale(0.7))

        // Visualize with a shaded area
        let axes = Axes(x_range: [0, 5, 1], y_range: [0, 4, 1])
        axes.scale(0.6)
        axes.shift(DOWN * 1.5)

        let graph = axes.plot(|x| 0.1 * x * x + 0.5, color: YELLOW)
        let area = axes.get_area(graph, x_range: [1, 4], color: BLUE, opacity: 0.3)

        self.play(Create(axes))
        self.play(Create(graph))
        self.play(FadeIn(area))

        let a_label = MathTex("a", color: RED)
        a_label.scale(0.6)
        a_label.next_to(axes.c2p(1, 0), DOWN)
        let b_label = MathTex("b", color: RED)
        b_label.scale(0.6)
        b_label.next_to(axes.c2p(4, 0), DOWN)
        self.play(Write(a_label), Write(b_label))
        self.wait(1.5)

        self.play(
            FadeOut(title), FadeOut(theorem), FadeOut(axes),
            FadeOut(graph), FadeOut(area), FadeOut(a_label), FadeOut(b_label)
        )
    }
}
from manim import *

class ComplexMath(Scene):
    def construct(self):
        title = Text('The Fundamental Theorem of Calculus', color=BLUE)
        title.scale(0.6)
        title.to_edge(UP)
        self.play(Write(title))
        theorem = MathTex('\\int_a^b f(x)\\,dx = F(b) - F(a)')
        theorem.scale(1.3)
        self.play(Write(theorem))
        self.wait(1)
        self.play(theorem.animate.shift((UP * 0.5)).scale(0.7))
        axes = Axes(x_range=[0, 5, 1], y_range=[0, 4, 1])
        axes.scale(0.6)
        axes.shift((DOWN * 1.5))
        graph = axes.plot(lambda x: ((0.1 * x * x) + 0.5), color=YELLOW)
        area = axes.get_area(graph, x_range=[1, 4], color=BLUE, opacity=0.3)
        self.play(Create(axes))
        self.play(Create(graph))
        self.play(FadeIn(area))
        a_label = MathTex('a', color=RED)
        a_label.scale(0.6)
        a_label.next_to(axes.c2p(1, 0), DOWN)
        b_label = MathTex('b', color=RED)
        b_label.scale(0.6)
        b_label.next_to(axes.c2p(4, 0), DOWN)
        self.play(Write(a_label), Write(b_label))
        self.wait(1.5)
        self.play(FadeOut(title), FadeOut(theorem), FadeOut(axes),
            FadeOut(graph), FadeOut(area), FadeOut(a_label), FadeOut(b_label))
15

Advanced Animation Orchestration

What you will learn

  • LaggedStart() creates cascading staggered animations
  • AnimationGroup() runs multiple animations simultaneously
  • Succession() chains animations sequentially
  • lag_ratio: controls the stagger timing
// Tutorial 15: Advanced Animations
// AnimationGroup, LaggedStart, Succession

scene AdvancedAnimation {
    fn construct(self) {
        let title = Text("Advanced Animations", color: BLUE)
        title.scale(0.7)
        title.to_edge(UP)
        self.play(Write(title))

        // Build 6 colored circles
        let c0 = Circle(radius: 0.3, color: RED)
        c0.set_fill(RED, opacity: 0.5)
        let c1 = Circle(radius: 0.3, color: ORANGE)
        c1.set_fill(ORANGE, opacity: 0.5)
        let c2 = Circle(radius: 0.3, color: YELLOW)
        c2.set_fill(YELLOW, opacity: 0.5)
        let c3 = Circle(radius: 0.3, color: GREEN)
        c3.set_fill(GREEN, opacity: 0.5)
        let c4 = Circle(radius: 0.3, color: BLUE)
        c4.set_fill(BLUE, opacity: 0.5)
        let c5 = Circle(radius: 0.3, color: PURPLE)
        c5.set_fill(PURPLE, opacity: 0.5)

        let group = VGroup(c0, c1, c2, c3, c4, c5)
        group.arrange(RIGHT, buff: 0.4)

        // LaggedStart - cascading creation
        self.play(LaggedStart(
            Create(c0), Create(c1), Create(c2),
            Create(c3), Create(c4), Create(c5),
            lag_ratio: 0.2
        ))

        // AnimationGroup - all at once
        self.play(AnimationGroup(
            c0.animate.shift(UP),
            c1.animate.shift(UP * 0.5),
            c2.animate.shift(DOWN * 0.5),
            c3.animate.shift(DOWN),
            c4.animate.shift(UP * 0.5),
            c5.animate.shift(UP)
        ))

        // Succession - one after another
        self.play(Succession(
            c0.animate.set_color(WHITE),
            c1.animate.set_color(WHITE),
            c2.animate.set_color(WHITE),
            c3.animate.set_color(WHITE),
            c4.animate.set_color(WHITE),
            c5.animate.set_color(WHITE)
        ))
        self.wait(1)

        self.play(FadeOut(group), FadeOut(title))
    }
}
from manim import *

class AdvancedAnimation(Scene):
    def construct(self):
        title = Text('Advanced Animations', color=BLUE)
        title.scale(0.7)
        title.to_edge(UP)
        self.play(Write(title))
        c0 = Circle(radius=0.3, color=RED)
        c0.set_fill(RED, opacity=0.5)
        c1 = Circle(radius=0.3, color=ORANGE)
        c1.set_fill(ORANGE, opacity=0.5)
        c2 = Circle(radius=0.3, color=YELLOW)
        c2.set_fill(YELLOW, opacity=0.5)
        c3 = Circle(radius=0.3, color=GREEN)
        c3.set_fill(GREEN, opacity=0.5)
        c4 = Circle(radius=0.3, color=BLUE)
        c4.set_fill(BLUE, opacity=0.5)
        c5 = Circle(radius=0.3, color=PURPLE)
        c5.set_fill(PURPLE, opacity=0.5)
        group = VGroup(c0, c1, c2, c3, c4, c5)
        group.arrange(RIGHT, buff=0.4)
        self.play(LaggedStart(Create(c0), Create(c1), Create(c2),
            Create(c3), Create(c4), Create(c5), lag_ratio=0.2))
        self.play(AnimationGroup(c0.animate.shift(UP),
            c1.animate.shift((UP * 0.5)), c2.animate.shift((DOWN * 0.5)),
            c3.animate.shift(DOWN), c4.animate.shift((UP * 0.5)),
            c5.animate.shift(UP)))
        self.play(Succession(c0.animate.set_color(WHITE),
            c1.animate.set_color(WHITE), c2.animate.set_color(WHITE),
            c3.animate.set_color(WHITE), c4.animate.set_color(WHITE),
            c5.animate.set_color(WHITE)))
        self.wait(1)
        self.play(FadeOut(group), FadeOut(title))

Congratulations!

You have completed all 15 MathViz tutorials. You now know how to:

  • Create and animate shapes, text, and LaTeX formulas
  • Position, style, and transform objects
  • Plot mathematical functions on axes and number planes
  • Use groups, updaters, and value trackers for dynamic scenes
  • Build 3D scenes with camera control
  • Orchestrate complex animations with LaggedStart, AnimationGroup, and Succession