4.0 Creating Text
There is a special subclass of Mobject called a TextMobject (a text math object). Add the following class to your
manim_tutorial_1.py file and type
python extract_scene.py manim_tutorial_1.py Shapes -pl at the command line. Note that the text looks really fuzzy because we are rending the animations at low quality to speed things up. With a small file like this you could render it at full resolution without taking too much time. To do this, replace
-p (leaving off the low resolution tag).
class AddingText(Scene): #Adding text on the screen def construct(self): my_first_text=TextMobject("Writing with manim is fun") second_line=TextMobject("and easy to do!") second_line.next_to(my_first_text,DOWN) third_line=TextMobject("for me and you!") third_line.next_to(my_first_text,DOWN) self.add(my_first_text, second_line) self.wait(2) self.play(Transform(second_line,third_line)) self.wait(2) second_line.shift(3*DOWN) self.play(ApplyMethod(my_first_text.shift,3*UP))
To create a textmobject you must pass it a valid string as an argument. Text rendering is based on Latex so you can use many Latex typesetting features; I’ll get into that in a later post. As a subclass of mobjects, any method such as
next_to can be used with textmobjects.
wait() method will prevent the next command for the scene from being executed for the desired number of seconds. The default time is 1 second so calling
self.wait() will wait 1 second before executing the next command in your script.
You should notice that, during the animation, the second line jumps down while the top line gently glides up. This has to do with the fact that we applied the
shift() method to the second line but we created an animation of the shift to the first line. When animating a
mobject() method the
ApplyMethod() animation is needed. Notice the arguments of
ApplyMethod() is a pointer to the method (in this case
my_first_text.shift without any parentheses) followed by a comma and then the what you would normally include as the argument to the
shift() method. In other words,
ApplyMethod(my_first_text.shift,3*UP) will create an animation of shifting
my_first_text three MUnits up.
4.1 Changing Text
Add this code to your tutorial file and extract the following scene.
class AddingMoreText(Scene): #Playing around with text properties def construct(self): quote = TextMobject("Imagination is more important than knowledge") quote.set_color(RED) quote.to_edge(UP) quote2 = TextMobject("A person who never made a mistake never tried anything new") quote2.set_color(YELLOW) author=TextMobject("-Albert Einstein") author.scale(0.75) author.next_to(quote.get_corner(DOWN+RIGHT),DOWN) self.add(quote) self.add(author) self.wait(2) self.play(Transform(quote,quote2),ApplyMethod(author.move_to,quote2.get_corner(DOWN+RIGHT)+DOWN+2*LEFT)) self.play(ApplyMethod(author.match_color,quote2)) self.play(FadeOut(quote))
Here we see how to change the color of text using
set_color(). This uses the same colors discussed in relation to drawing geometric shapes, many of which are defined in the
COLOR_MAP dictionary in
constants.py. In addition to setting the color, you can also match the color to another object. In the second to last line of code above we use
match_color() to change the color of the
author to match
You can change the size of text using
scale(). This method scales the mobject up by the numerical factor given. Thus
scale(2) will double the size of a mobject while
scale(0.3) will shrink the mobject down to 30% of its size. It doesn’t seem you can use
scale() in an animation (
ApplyMethod(author.scale,2) doesn’t work). There is probably a better way around this but what I would do if I wanted to animate a scale-up or down is create a second textmobject that
is the final size I want and use
Transform() to smoothly shift from one scale to another. Hopefully I’ll figure out a better way to do this later on.
You can align mobjects with the center of the edge of the screen by telling
to_edge() whether you want the object to be
RIGHT. You can also use
to_corner(), in which case you need to combine two directions such as
UP+LEFT to indicate the corner.
Each mobject has a bounding box and you can get the coordinates of the corners of this bounding box using
get_corner() and specifying a direction. Thus
get_corner(DOWN+LEFT) will return the location of the lower left corner of a mobject. In our example we find the lower right corner of
quote and place the author one unit down from that point. Later we move the
author down and slightly left of
An important thing to note is that the
Transform() animation still leaves the mobject
quote on the screen but has just changed its display text and properties to be those of
quote2. This is why
FadeOut() refers to
quote and not
quote2. However, the corner of
quote is where it was originally, which is why we have to find the corner of
quote2 to move
author to the correct location. Keep in mind that when you use
Tranform, properties of the mobects involved might not be what you think they are so beware.
Another useful piece of information is that the
scale() method changes the size of the objects as it currently is. In other words, using
scale(.5) followed by
scale(.25) results in an object that is $0.5*0.25 = 0.125$ times the original size
Things to try:
– Try using the
– Check out
COLOR_MAP in the
constants.py file and change the color of the text
4.2 Rotating and Highlighting Text
The following code will demonstrate how to rotate text and give it some pizzazz. As usual, copy the code into your tutorial file and extract it using
python extract_scene.py manim_tutorial_1.py RotateAndHighlight -p
class RotateAndHighlight(Scene): #Rotation of text and highlighting with colors and rectangles def construct(self): square=Square(side_length=5,fill_color=YELLOW, fill_opacity=1) label=TextMobject("Text at an angle") label.bg=BackgroundRectangle(label,fill_opacity=1) label_group=VGroup(label.bg,label) #Order matters label_group.rotate(TAU/8) label2=TextMobject("Boxed text",color=RED) label2.bg=SurroundingRectangle(label2,color=BLUE,fill_color=RED, fill_opacity=.5) label2_group=VGroup(label2,label2.bg) label2_group.next_to(label_group,DOWN) label3=TextMobject("Rainbow") label3.scale(2) label3.set_color_by_gradient(RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE) label3.to_edge(DOWN) self.add(square) self.play(FadeIn(label_group)) self.play(FadeIn(label2_group)) self.play(FadeIn(label3))
We’ve added a square in the background to show what
BackgroundRectangle does. Note that the opacity of the fill color defaults to zero so if you don’t define the
fill_opacity you only see the edges of the square. To create a background rectange you need to specify the textmobject to apply this method to, as well as the opacity. You can’t change the color background to anything but black.
VGroup class allows you to combine multiple mobjects into a single vectorized math object. This allows you to apply any
VMobject methods to the all elements of the group. You are still able change properties of the orignal mobjects after they are groups. In other words, the original mobjects are not destroyed, the vmobject is just a higher level grouping of the mobjects. By grouping the text and the background rectangle we can then use
rotate() to change the orientation of both objects together. Note that
TAU is equal to $2 \pi$ (see the Tau Manifesto, which makes some interesting points).
next_to() method can be thought of as a shift relative to some other object so
label2_group shifted down one unit from
label1_group (remember that the unit of distance is set by the
FRAME_HEIGHT variable in
constants.py and the default screen height is 8 units).
You can create a a color gradient using
set_color_by_gradient(). Pass the method any number of colors, separated by commas.
Things to play with
– Try changing the fill opacity for both the square and the background rectangle
– Try rotating the background rectangle separately from the the text
– Change the color of label2 to see how it affects the readability of the text
– Change the colors of “Rainbow”
– Place the “Rainbow” text on a different edge of the screen.
NOTE: If anything in these posts isn’t making sense, please leave a comment. I hope to continue to edit these posts to clarify and help people learn how to use manim so feedback is appreciated.
You can find a copy of this code at https://github.com/zimmermant/manim_tutorial