How to Import and Utilize SVG Files Using SVGMobject in Manim Animations

Use SVGMobject to convert any SVG file or raw SVG markup into a vectorized Manim object that supports standard transformations, styling overrides, and granular sub-object animation.

To import and utilize SVG files using SVGMobject in Manim animations, you leverage the vector graphics pipeline in the 3b1b/manim repository. This class transforms static SVG data into a hierarchy of VMobject instances, enabling you to animate complex logos, diagrams, and illustrations with the same API used for native Manim primitives.

How SVGMobject Processes SVG Data Internally

SVGMobject inherits from VMobject (defined at manimlib/mobject/svg/svg_mobject.py:L53), which provides the foundational vector functionality for strokes, fills, and geometric transformations. The initialization sequence (__init__ at lines 58–78) accepts either a file_name or an svg_string, stores user-provided style overrides, and triggers the build pipeline.

The construction process follows these stages:

Caching and Hashing – The system computes a hash seed (lines 134–144) based on the class name, default style dictionary, path string configuration, and raw SVG data. This populates SVG_HASH_TO_MOB_MAP and PATH_TO_POINTS, ensuring that identical SVGs are parsed only once.

XML Preprocessing – The method modify_xml_tree (lines 161–185) strips original root attributes, creates a fresh <svg> element, and injects a configuration style node. This isolates the SVG from viewBox unit conversions and allows Manim to reliably apply global style overrides.

Element Conversionmobjects_from_svg (lines 203–227) walks the parsed svgelements.SVG object and dispatches each primitive—Path, Line, Rect, Circle, Ellipse, Polygon, Polyline—to dedicated helpers like path_to_mobject or line_to_mobject.

Path ParsingVMobjectFromSVGPath (lines 336–424) handles the heavy lifting of converting SVG path commands (move, line, cubic/quadratic Bezier, arcs) into Manim point arrays. Results are cached in PATH_TO_POINTS to accelerate repeated use.

Coordinate Adjustment – After construction, init_svg_mobject (lines 123–133) flips the Y-axis (self.flip(RIGHT)) to align SVG coordinates with Manim’s coordinate system where positive Y is up.

Importing and Using SVG Files in a Scene

Follow these steps to integrate external vector graphics into your animation.

1. Import the Class

from manim import *

2. Instantiate from File or String

Place your SVG file in the media directory or provide an absolute path. Alternatively, pass raw markup.


# Load from disk

logo = SVGMobject("company_logo.svg")

# Load from raw string

raw_svg = """<svg viewBox="0 0 100 100">
               <rect x="10" y="10" width="80" height="80" fill="blue"/>
             </svg>"""
icon = SVGMobject(svg_string=raw_svg)

3. Apply Transformations and Styling

logo.set_height(4)                    # Scale to 4 Manim units

logo.move_to(ORIGIN)                  # Center in frame

logo.set_fill(PURE_RED, opacity=0.8)  # Override SVG fill

logo.set_stroke(WHITE, width=2)       # Override stroke

4. Animate Sub-objects

The SVG hierarchy exposes individual paths as submobjects.


# Sequential fade-in of each path

self.play(LaggedStartMap(FadeIn, logo.submobjects, lag_ratio=0.1))

# Color cycle individual elements

for i, submob in enumerate(logo.submobjects):
    submob.set_color([RED, GREEN, BLUE][i % 3])

Advanced SVGMobject Techniques

Leverage these strategies for production-quality animations.

Global Color Override – Pass color, fill_color, or stroke_color to the constructor. These values feed into generate_config_style_dict (lines 186–202) and are injected into the SVG’s style node, affecting every path element uniformly.

Selective Partial Styling – After construction, index specific sub-objects (logo[0], logo[3]) to apply distinct styles. This is effective for multi-color logos where you need to preserve brand colors on specific elements.

Caching for Performance – The internal SVG_HASH_TO_MOB_MAP ensures that repeated instantiations of the same SVG (e.g., inside a loop or function) reuse pre-parsed geometry. No manual intervention is required; simply instantiate normally.

Custom Path Parsing – For SVGs with non-standard elements, subclass SVGMobject and override path_to_mobject or modify_xml_tree. This allows bespoke handling of custom markers or proprietary SVG extensions while retaining the base rendering pipeline.

LaTeX-Style Text via StringMobject – For animated typography, use StringMobject (located in manimlib/mobject/svg/string_mobject.py). It builds upon SVGMobject and adds text-selection utilities, making it ideal for equations and formatted text animations.

Complete Code Examples

Example 1: Simple SVG Import and Basic Animation

from manim import *

class SvgDemo(Scene):
    def construct(self):
        # Load the SVG file placed in the "media/svg_images" folder

        logo = SVGMobject("3b1b_logo.svg")
        logo.set_height(3)                # Scale to a convenient size

        logo.move_to(UP)                  # Position near the top

        # Animate the whole logo

        self.play(FadeIn(logo, shift=UP))
        self.wait(1)

        # Animate the individual parts with a lag

        self.play(
            LaggedStartMap(
                Rotate,
                logo.submobjects,
                angle=TAU,
                run_time=3,
                lag_ratio=0.15,
            )
        )
        self.wait()

Key implementation details:

  • SVGMobject("3b1b_logo.svg") triggers file_name_to_svg_string (lines 158–160) to locate and read the file.
  • logo.submobjects exposes the vectorized hierarchy created by mobjects_from_svg (lines 203–227).

Example 2: Overriding Colors and Combining with Other Objects

from manim import *

class SvgStyleDemo(Scene):
    def construct(self):
        # Load an SVG of a lightbulb

        bulb = SVGMobject("lightbulb.svg")
        bulb.set_fill(WHITE, opacity=0.8)   # Force a light fill

        bulb.set_stroke(GREY, width=3)     # Override stroke

        # Create a surrounding frame

        frame = Rectangle(width=8, height=5, color=BLUE_D).surround(bulb)

        # Group them

        group = VGroup(frame, bulb).center()

        # Animate the group appearing

        self.play(Write(frame))
        self.play(FadeIn(bulb, scale=0.5))
        self.wait()

Example 3: Generating an SVG from a String

from manim import *

class SvgFromString(Scene):
    def construct(self):
        raw = """
        <svg viewBox="0 0 100 100">
            <polygon points="10,10 90,10 50,80" fill="orange"/>
            <circle cx="50" cy="30" r="10" fill="purple"/>
        </svg>
        """
        shape = SVGMobject(svg_string=raw)
        shape.scale(2).move_to(ORIGIN)

        self.play(FadeIn(shape))
        self.wait()

Summary

  • SVGMobject converts SVG files or raw markup into manipulable VMobject hierarchies via manimlib/mobject/svg/svg_mobject.py.
  • The constructor accepts either file_name or svg_string, automatically handling XML preprocessing, Y-axis flipping, and style injection through modify_xml_tree and generate_config_style_dict.
  • Internal caching via SVG_HASH_TO_MOB_MAP and PATH_TO_POINTS eliminates redundant parsing of identical graphics.
  • Each SVG element becomes a submobject accessible through .submobjects, enabling granular animation of individual paths, shapes, or groups.
  • Style overrides applied at construction time or via set_fill/set_stroke affect the entire object, while indexing specific submobjects allows partial colorization.

Frequently Asked Questions

How do I position an SVG file correctly in the scene?

Place your SVG file in the media/ directory or a subdirectory within your project path. SVGMobject uses get_full_vector_image_path (defined in manimlib/utils/images.py) to resolve the file location. Once loaded, use .move_to(ORIGIN), .to_edge(UP), or .shift(RIGHT * 2) to position the object using standard Manim coordinates.

Can I animate individual parts of an imported SVG separately?

Yes. SVGMobject parses the SVG into a hierarchy of submobjects—one for each path, rectangle, circle, or polygon. Access these via the .submobjects attribute or by indexing (e.g., svg[0], svg[1]). You can then apply distinct styles or animations to each element, such as svg[0].set_fill(RED) or LaggedStartMap(FadeIn, svg.submobjects).

Why does my SVG appear upside down or mirrored?

Manim automatically flips the Y-axis during construction via self.flip(RIGHT) inside init_svg_mobject (lines 123–133 of svg_mobject.py). This corrects the coordinate mismatch between SVG standards (where Y increases downward) and Manim’s scene coordinates (where Y increases upward). If your graphic still appears incorrect, verify that your SVG’s viewBox and width/height attributes are properly defined, as these guide the scaling logic in modify_xml_tree.

How can I override the colors defined in the original SVG file?

Pass style arguments directly to the SVGMobject constructor, such as fill_color=PURE_BLUE, stroke_color=WHITE, or color=RED. These values feed into generate_config_style_dict (lines 186–202), which creates a configuration style node injected into the SVG XML. This node globally overrides attributes for all path elements. Alternatively, call set_fill() or set_stroke() after instantiation to apply styles post-construction.

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 →