How to Render LaTeX Equations and Text Using TexMobject in Manim Animations

Manim renders LaTeX by converting strings to SVG images through external compilers, wrapping them in the Tex class that handles scaling, coloring, and symbol isolation for animation.

In the 3b1b/manim library, mathematical typesetting is powered by the Tex class (historically referred to as TexMobject) defined in manimlib/mobject/svg/tex_mobject.py. This Mobject compiles LaTeX source into scalable vector graphics, enabling precise control over individual symbols and seamless integration with Manim's animation system.

The LaTeX-to-SVG Architecture

Manim's LaTeX rendering relies on three coordinated components that transform raw strings into animatable Mobjects.

Core Components

The Compilation Pipeline

When you instantiate Tex(r"E=mc^2"), the following sequence occurs:

  1. String Processing: The Tex.__init__ method (lines 38-79) stores the raw LaTeX string and merges the tex_to_color_map dictionary with legacy t2c arguments (line 67).

  2. SVG Generation: The method get_svg_string_by_content forwards the string to latex_to_svg (lines 81-83), which builds a temporary LaTeX document via get_full_tex.

  3. External Compilation: latex_to_svg (lines 50-82) selects a compiler and preamble from get_tex_config, writes the temporary file, invokes the LaTeX compiler and dvisvgm, and returns the SVG string.

  4. Scaling Calibration: The resulting Mobject is scaled by get_tex_mob_scale_factor() * font_size (lines 77-78). This factor is computed by rendering a reference "0" and measuring its height, ensuring a font_size of 48 yields a height of 1 Manim unit.

  5. Color Injection: The set_color_by_tex_to_color_map method (line 76) parses the LaTeX source to find matching spans and injects \color[RGB]{…} commands via get_color_command and get_command_string.

Configuring Templates and Unicode Support

The template argument (line 44) allows switching between LaTeX engines without modifying source code. This is essential for Unicode support or TikZ graphics.

from manim import *

class UnicodeExample(Scene):
    def construct(self):
        text = Tex(
            r"\text{Привет, мир!}",
            template="xelatex"  # Uses xelatex compiler from tex_templates.yml

        )
        self.play(Write(text))
        self.wait()

The tex_templates.yml file defines the compiler path, preamble packages, and font settings for each template name.

Isolating Symbols for Granular Animation

The isolate argument (lines 51-56) marks specific substrings as separate sub-Mobjects, enabling individual symbol animation.

class IsolateExample(Scene):
    def construct(self):
        expr = Tex(r"x^2 + y^2 = r^2", isolate=["x", "y", "r"])
        x, y, r = expr.get_parts_by_tex(["x", "y", "r"])
        
        self.play(Write(expr))
        self.play(
            x.animate.shift(UP),
            y.animate.shift(LEFT),
            r.animate.scale(2)
        )
        self.wait()

Each isolated part becomes its own sub-Mobject accessible via get_parts_by_tex, allowing targeted transformations.

Coloring Mathematical Expressions

Use tex_to_color_map to apply colors to specific symbols without manual index tracking. The class automatically injects color commands into the generated LaTeX.

class ColorMapExample(Scene):
    def construct(self):
        formula = Tex(
            r"\frac{a}{b} = c",
            tex_to_color_map={"a": RED, "b": BLUE, "c": GREEN}
        )
        self.play(FadeIn(formula))
        self.wait()

Performance Optimization Through Caching

Both latex_to_svg and get_tex_mob_scale_factor are decorated with @lru_cache (as implemented in manimlib/utils/tex_file_writing.py). Identical LaTeX strings compile only once per session, dramatically reducing render times for repeated equations.

Handling Edge Cases

The Tex class includes safeguards for common LaTeX issues:

  • Empty Strings: Automatically substitutes a dummy line break (\\) to prevent LaTeX compilation errors (lines 59-62).
  • Alignment Environments: Supports standard LaTeX environments like align* through the raw string interface.
class AlignExample(Scene):
    def construct(self):
        system = Tex(r"""
            \begin{align*}
                a &= b + c \\
                d &= e - f
            \end{align*}
        """, font_size=72)
        self.play(FadeIn(system))
        self.wait()

Summary

  • Manim's Tex class (located in manimlib/mobject/svg/tex_mobject.py) converts LaTeX strings to SVG via external compilers.
  • The latex_to_svg utility in manimlib/utils/tex_file_writing.py handles the LaTeX → DVI → SVG pipeline with LRU caching for performance.
  • Scaling is calibrated automatically so that font_size=48 equals 1 Manim unit height.
  • tex_to_color_map injects color commands automatically; isolate creates separate sub-Mobjects for individual symbol animation.
  • Templates defined in manimlib/tex_templates.yml enable switching between compilers (e.g., xelatex for Unicode) via the template argument.

Frequently Asked Questions

What is the difference between Tex and TexMobject in Manim?

In the 3b1b/manim library, the class is named Tex and is defined in manimlib/mobject/svg/tex_mobject.py. Older documentation and community versions often refer to this functionality as "TexMobject," but the modern implementation uses the Tex class with an improved API including tex_to_color_map and isolate parameters.

Why is my LaTeX compilation slow on the first run?

Manim must invoke external LaTeX compilers and dvisvgm to generate SVG files. However, the latex_to_svg function uses @lru_cache to store results. Subsequent uses of identical LaTeX strings retrieve the cached SVG instantly, eliminating compilation overhead.

How do I use Unicode characters or custom fonts in Manim equations?

Pass template="xelatex" to the Tex constructor. This selects the XeLaTeX compiler configuration from manimlib/tex_templates.yml, which supports Unicode input and system fonts. Ensure your LaTeX installation includes xelatex and the necessary font packages.

Can I animate individual parts of a fraction or subscript?

Yes. Use the isolate parameter when creating the Tex object, passing a list of strings to treat as separate sub-Mobjects. For example, Tex(r"\frac{a}{b}", isolate=["a", "b"]) allows you to target the numerator and denominator independently via get_parts_by_tex("a") and standard animation methods.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →