Search code examples
svgmanim

SVGMobject doesn't display the image correctly


I am trying to create a number creature using a SVG file. But when I run the animation and the creature appears, there are some missing parts and I can't figure why. Even if I just try to load the SVG file on a SVGMobject, it doesn't work properly.

Creature() is a child class that inherits the functionality from NumberCreature class, just renamed Alex().

Here it is the python code:

class NumberCreature(Scene):
def construct(self):       
    creature = Creature()
    self.add(creature)
    self.wait()

Here it is the original SVG code: https://codeshare.io/aYM4Mn Here it is the expected result: SVG original image

When I run the python code, this is the real result: SVG generated image by manim

I also tried to run this python code:

class NumberCreature(Scene):
def construct(self):       
creature = SVGMobject('/home/usr/manim/assets/svg_images/NumberCreature_plain.svg')    
    self.add(creature)
    self.wait()

results from manim

As you can see, there are parts of the image missing, and even if I try to color everything correctly using creature[index].set_color(original_hex_color), the result is always different from original.

Please help me, I don't know exactly what's happening, I am noob on manim yet.


Solution

  • If you are going to use SVG in manim, it is recommended that you take some basic SVG course, because surely you are going to face this kind of problems very often, you can find quite a lot on youtube, I recommended you start with this.

    Solving your question, to analyze what happens I have created a script:

            creature = SVGMobject('creature.svg').set_height(FRAME_HEIGHT-1)
            index = VGroup()
            colors = it.cycle([YELLOW,GREEN,PURPLE,PINK,GRAY,TEAL])
            for i in range(len(creature)):
                text = Text(f"{i}",color=WHITE,stroke=0,font="Arial").set_height(0.4)
                color = next(colors)
                creature[i].set_color(color)
                creature[i].set_stroke(color,2)
                text.next_to(creature[i],RIGHT,buff=0)
                index.add(text)
    

    enter image description here

    This script shows me the number of parts that the svg has, and I position the indexes to the right of each part, as you can see in the image, there are 8 (start with 0) subfigures in the svg, and we can intuit that layer 0 and 7 are the same, so if we hide layer 7 give us:

    class NumberCreature(Scene):
        def construct(self):
            creature = SVGMobject('creature.svg').set_height(FRAME_HEIGHT-1)
            index = VGroup()
            colors = it.cycle([YELLOW,GREEN,PURPLE,PINK,GRAY,TEAL])
            for i in range(len(creature)):
                text = Text(f"{i}",color=WHITE,stroke=0,font="Arial").set_height(0.4)
                color = next(colors)
                creature[i].set_color(color)
                creature[i].set_stroke(color,2)
                text.next_to(creature[i],RIGHT,buff=0)
                index.add(text)
    
            creature.set_stroke(BLUE,2)
            creature[-1].fade(1)
    
            self.add(creature,index)
            self.wait()
    

    enter image description here

    Knowing this, it is not difficult to intuit what is happening, and you have to work on the design.

    IMPORTANT: By default, manim removes styles and colors from svg, so you will have to configure them manually, as follows:

    class NumberCreatureS(Scene):
        def construct(self):
            creature = SVGMobject('creature.svg').set_height(FRAME_HEIGHT-1)
            creature[0].set_style(fill_opacity=1,stroke_width=0,stroke_opacity=0,fill_color=RED_A)
            creature[7].set_style(fill_opacity=0,stroke_width=30,stroke_opacity=1,stroke_color=RED)
            creature[3].set_stroke(RED,20)
            black_rectangle = Rectangle(
                width=get_norm(creature[0].get_corner(UL)-creature[0].get_corner(UR)),
                height=creature[1].get_height()/2,
                fill_opacity=1,
                stroke_opacity=0,
                fill_color=BLACK,
                )
            black_rectangle.next_to(creature[0],UP,buff=0.15)
    
            self.add(creature,black_rectangle)
            self.wait()
    

    enter image description here