Important Note: These posts are based on an earlier version of manim which uses Python 2.7. The latest version of manim is using Python 3. To follow along with these posts, use Python 2.7 and the May 9, 2018 commit of manim .
3.0 More Shapes
You can create almost any geomtric shape using manim. You can create circles, squares, rectangles, ellipses, lines, and arrows. Let’s take a look at how to draw some of those shapes.
Copy and paste the code below into your
manim_tutorial_1.py file and type the following into the command line to run this scene:
python extract_scene.py manim_tutorial_1.py MoreShapes -pl.
class MoreShapes(Scene): #A few more simple shapes def construct(self): circle = Circle(color=PURPLE_A) square = Square(fill_color=GOLD_B, fill_opacity=1, color=GOLD_A) square.move_to(UP+LEFT) circle.surround(square) rectangle = Rectangle(height=2, width=3) ellipse=Ellipse(width=3, height=1, color=RED) ellipse.shift(2*DOWN+2*RIGHT) pointer = CurvedArrow(2*RIGHT,5*RIGHT,color=MAROON_C) arrow = Arrow(LEFT,UP) arrow.next_to(circle,DOWN+LEFT) rectangle.next_to(arrow,DOWN+LEFT) ring=Annulus(inner_radius=.5, outer_radius=1, color=BLUE) ring.next_to(ellipse, RIGHT) self.add(pointer) self.play(FadeIn(square)) self.play(Rotating(square),FadeIn(circle)) self.play(GrowArrow(arrow)) self.play(GrowFromCenter(rectangle), GrowFromCenter(ellipse), GrowFromCenter(ring))
You’ll notice we have a few new shapes and we are using a couple of new commands. Previously we saw the
Polygon() classes. Now we’ve added
CurvedArrow(). All shapes, with the exception of lines and arrows, are created at the origin (center of the screen, which is (0,0,0)). For the lines and arrows you need to specify the location of the two ends.
For starters, we’ve specified a color for the square using the keyword argument
color=. Most of the shapes are subclasses of VMobject, which stands for a vectorized math object.
VMobject is itself a subclass of the math object class
Mobject. The best way to determine the keyword arguments you can pass to the classes are to take a look at the allowed arguments for the VMobject and Mobject class. Some possible keywords include
fill_opacity. For the
Annulus() class we have
outer_radius for keyword arguments.
A list of the named colors can be found in the
COLOR_MAP dictionary located in the
constant.py file. The named colors are keys to the
COLOR_MAP dictionary which yield the hex color code. You can create your own colors using a hex color code picker (Google it and adding entries to
3.1 Direction Vectors
constants.py file contains other useful defintions, such as direction vectors that can be used to place objects in the scene. For example,
UP is a numpy array (0,1,0), which corresponds to 1 unit of distance. To honor the naming convention used in manim I’ve decided to call the units of distance the MUnit or math unit (this is my own term, not a manim term). Thus the default screen height is 8 MUnits (as defined in
constants.py). The default screen width is 14.2 MUnits.
If we are thinking in terms of x-, y-, and z-coordinates,
UP is a vector pointing along the positive y-axis.
RIGHT is the array (1,0,0) or a vector pointing along the positive x-axis. The other direction vectors are
OUT. Each vector has a length of 1 MUnit. After creating an instance of an object you can use the
.move_to() method to move the object to a specific location on the screen. Notice that the direction vectors can be added together (such as
UP+LEFT) or multiplied by a scalar to scale it up (like
2*RIGHT). In other words, the direction vectors act like you would expect mathematical vectors to behave. If you want to specify your own vectors, they will need to be numpy arrays with three components. The center edge of each screen side is also defined by vectors
The overall scale of the vectors (the relationship between pixels and MUnits) is set by the
FRAME_HEIGHT variable defined in
constants.py. The default value for this is 8. This means you would have to move an object
8*UP to go from the bottom of the screen to the top of the screen. At this time I don’t see a way to change it other than by changing it in
Mobjects can also be located relative to another object using the
next_to() method. The command
arrow.next_to(circle,DOWN+LEFT) places the arrow one MUnit down and one to the left of the circle. The rectangle is then located one MUnit down and one left of the arrow.
Circle() class has a
surround() method that allows you to create a circle that completely encloses another mobject. The size of the circle will be determined by the largest dimension of the mobject surrounded.
3.2 Making Simple Animations
As previously mentioned, the
.add() method places a mobject on screen at the start of the scene. The
.play() method can be used animate things in your scene.
The names of the animations, such as
GrowFromCenter, are pretty self-explanatory. What you should notice is that animations play sequentially in the order listed and that if you want multiple animations to occur simultaneously, you should include all those animations in the argument of a single
.play() command separated by commas. I’ll show you how to use lists of animations to play multiple animations at the same time in a later entry in this series.
Things to try:
– Use the
Polygon() class to create other shapes
– Try placing multiple objects on the screen at various locations
– Take a look at the different types of transformations available in
Next time we will take a look at writing text on the screen.