Example Gallery¶
Hi! FlyingFrames is a project by me (kolibril13), where I want to provide you some tutorials and code snippets that I often use when I prepare my animations for my youtube channel: https://www.youtube.com/channel/UCq-aIJ8sN1-G2ZzIyWYostw
It does not replace the amazing documentation at https://docs.manim.community/en/stable/ , but I hope this blog will give you some inspiration for your future projects.
Content¶
Chapter 1 - Manim in Jupyter¶
Latest update : 18.6.2021
Working with manim in jupyter notebooks has several advantages:
code snippets and rendered outputs are close together
easy to iterate examples
easy to try different varieties of one scene in multiple cells
computation intensive code can be executed separately from the scenes
global Mobjects can be used in multiple scenes.
more can bee seen in chapter 4
Simple Example¶
First, we need to import manim
[1]:
from manim import *
Manim Community v0.8.0
Now we build up our scene
[2]:
%%manim -v WARNING --progress_bar None -s -ql --disable_caching MyExample
class MyExample(Scene):
def construct(self):
m= ManimBanner()
self.add(m)

Note, that I use the following parameters:
-v WARNING
means that only warnings are shown in the log--progress_bar None
will not show the animation progress bar-s
will only show the last frame-ql
renders in low quality--disable_caching
will disable the manim caching systemMyExample
gives the scene name
for rendering a video, just remove the -s flag. To lower the resolution, you can use -r 400,200 (pixel values in x and y direction).
[3]:
%%manim -v WARNING --progress_bar None -r 400,200 --disable_caching HelloManim
class HelloManim(Scene):
def construct(self):
self.camera.background_color = "#ece6e2"
banner_large = ManimBanner(dark_theme=False).scale(0.7)
self.play(banner_large.create())
self.play(banner_large.expand())
We can define the parameters as a string params
and call this string by the cell magic with $params
[4]:
params = "-v WARNING -s -ql --disable_caching Example"
paramsSMALL = "-v WARNING -r 400,200 -s --disable_caching Example"
[5]:
%%manim $params
class Example(Scene):
def construct(self):
m= ManimBanner()
self.add(m)

Initializing Mobjects Outside the Class¶
In some cases, it might be convenient to define mobjects outside the Scene
class (e.g. for uncluttering or for speeding up the animation).
[6]:
m = ManimBanner()
[7]:
%%manim $paramsSMALL
class Example(Scene):
def construct(self):
m.scale(0.4 )
m.shift(1.5*UP)
self.add(m)

Because the mobject is manipulated in the class, the next cell might show some unexpected scaling and shifting:
[8]:
%%manim $paramsSMALL
class Example(Scene):
def construct(self):
m.scale(0.4)
m.shift(1.5*UP)
self.add(m)

To aviod this, it is better to add only a copy of these mobjects to scenes, and keep the originals untouched:
[9]:
m_reference = ManimBanner()
[10]:
%%manim $paramsSMALL
class Example(Scene):
def construct(self):
m = m_reference.copy()
m.scale(0.4)
m.shift(2*UP)
self.add(m)

[11]:
%%manim $paramsSMALL
class Example(Scene):
def construct(self):
m = m_reference.copy()
m.scale(0.4)
m.shift(2*UP)
self.add(m)

Defining Global Mobjects¶
When you have to build complex scenes, you might want to use parts of that scene for your next scene. That is possible with global variables, which can be accessed in any other scene.
[12]:
%%manim $paramsSMALL
class Example(Scene):
def construct(self):
stars= VGroup()
for i in range(0,20):
s= Star(color= random_bright_color(), fill_opacity=1).scale(0.8)
stars.add(s)
stars.arrange_in_grid()
self.add(stars)
global favoritstar
favoritstar = stars[9]

[13]:
%%manim $paramsSMALL
class Example(Scene):
def construct(self):
self.add(favoritstar)

Pre-Execute Slow Code¶
%%time
command will print the execution time of the cells.[14]:
%%time
np.random.seed(20)
steps = np.random.choice(a=[-1, 0, 1], size=(100000,1000))
stop = steps.cumsum(0)
end_points= stop[-1]/stop[-1].max()
end_pointsX = end_points[0:499]
end_pointsY = end_points[500:-1]
CPU times: user 2.92 s, sys: 1.34 s, total: 4.25 s
Wall time: 4.26 s
[15]:
%%time
%%manim $params
class Example(Scene):
def construct(self):
radius= (end_pointsX*end_pointsX + end_pointsY * end_pointsY)**0.5
dots = VGroup()
for x,y,r in zip(end_pointsX, end_pointsY,radius):
c= interpolate_color(YELLOW, RED, r)
dots.add(Dot(color=c,point=[3*x,3*y,0]).scale(0.7))
self.add(dots)

CPU times: user 344 ms, sys: 0 ns, total: 344 ms
Wall time: 344 ms
Installing Plugins¶
plugins can be found at https://plugins.manim.community/
[16]:
!pip install manim-rubikscube
Collecting manim-rubikscube
Downloading manim_rubikscube-0.1.0-py2.py3-none-any.whl (7.5 kB)
Requirement already satisfied: manim in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim-rubikscube) (0.8.0)
Collecting kociemba-manim-rubikscube
Downloading kociemba_manim_rubikscube-0.0.1-py3-none-any.whl (33.3 MB)
|████████████████████████████████| 33.3 MB 4.7 MB/s
Requirement already satisfied: pydub in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (0.25.1)
Requirement already satisfied: rich>=6.0 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (10.4.0)
Requirement already satisfied: moderngl-window<3.0.0,>=2.3.0 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (2.4.0)
Requirement already satisfied: numpy<2.0,>=1.9 in /home/docs/.pyenv/versions/3.8.6/lib/python3.8/site-packages (from manim->manim-rubikscube) (1.19.2)
Requirement already satisfied: setuptools in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (57.0.0)
Requirement already satisfied: click>=7.1 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (8.0.1)
Requirement already satisfied: mapbox-earcut<0.13.0,>=0.12.10 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (0.12.10)
Requirement already satisfied: moderngl<6.0.0,>=5.6.3 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (5.6.4)
Requirement already satisfied: manimpango<0.4.0,>=0.3.0 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (0.3.0)
Requirement already satisfied: decorator<6.0.0,>=5.0.7 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (5.0.9)
Requirement already satisfied: tqdm in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (4.61.1)
Requirement already satisfied: networkx<3.0,>=2.5 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (2.5)
Requirement already satisfied: watchdog in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (2.1.3)
Requirement already satisfied: click-default-group in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (1.2.2)
Requirement already satisfied: colour in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (0.1.5)
Requirement already satisfied: pygments in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (2.9.0)
Requirement already satisfied: scipy in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (1.7.0)
Requirement already satisfied: Pillow<8.3.0 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (5.4.1)
Requirement already satisfied: requests in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (2.25.1)
Requirement already satisfied: screeninfo<0.7.0,>=0.6.7 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (0.6.7)
Requirement already satisfied: cloup<0.8.0,>=0.7.0 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (0.7.1)
Requirement already satisfied: pycairo<2.0,>=1.19 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from manim->manim-rubikscube) (1.20.1)
Requirement already satisfied: glcontext<3,>=2 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from moderngl<6.0.0,>=5.6.3->manim->manim-rubikscube) (2.3.4)
Requirement already satisfied: pyglet<2,>=1.5.8 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from moderngl-window<3.0.0,>=2.3.0->manim->manim-rubikscube) (1.5.18)
Requirement already satisfied: pyrr<1,>=0.10.3 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from moderngl-window<3.0.0,>=2.3.0->manim->manim-rubikscube) (0.10.3)
Requirement already satisfied: multipledispatch in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from pyrr<1,>=0.10.3->moderngl-window<3.0.0,>=2.3.0->manim->manim-rubikscube) (0.6.0)
Requirement already satisfied: colorama<0.5.0,>=0.4.0 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from rich>=6.0->manim->manim-rubikscube) (0.4.4)
Requirement already satisfied: commonmark<0.10.0,>=0.9.0 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from rich>=6.0->manim->manim-rubikscube) (0.9.1)
Requirement already satisfied: six in /home/docs/.pyenv/versions/3.8.6/lib/python3.8/site-packages (from multipledispatch->pyrr<1,>=0.10.3->moderngl-window<3.0.0,>=2.3.0->manim->manim-rubikscube) (1.15.0)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from requests->manim->manim-rubikscube) (1.26.6)
Requirement already satisfied: idna<3,>=2.5 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from requests->manim->manim-rubikscube) (2.10)
Requirement already satisfied: certifi>=2017.4.17 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from requests->manim->manim-rubikscube) (2021.5.30)
Requirement already satisfied: chardet<5,>=3.0.2 in /home/docs/checkouts/readthedocs.org/user_builds/flyingframes/envs/v0.8.0/lib/python3.8/site-packages (from requests->manim->manim-rubikscube) (4.0.0)
Installing collected packages: kociemba-manim-rubikscube, manim-rubikscube
Successfully installed kociemba-manim-rubikscube-0.0.1 manim-rubikscube-0.1.0
[17]:
%%manim -v WARNING --progress_bar None -ql --disable_caching Example
from manim_rubikscube import *
class Example(ThreeDScene):
def construct(self):
cube = RubiksCube().scale(0.6)
self.add(cube)
self.set_camera_orientation(phi=50*DEGREES, theta=160*DEGREES)
self.renderer.camera.frame_center = cube.get_center()
self.play(CubeMove(cube, "F"))
self.play(CubeMove(cube, "U2"), run_time=2)
self.play(CubeMove(cube, "R'"))
self.wait(0.5)
Chapter 2 - Mobject Basics¶
[1]:
from manim import *
Manim Community v0.8.0
[2]:
#ignore this cell, only for setup
params = "-v WARNING -r 500,100 -s --disable_caching Example"
paramsbigger = "-v WARNING -r 500,120 -s --disable_caching Example"
Positioning¶
First we want to position mobjects. There are tons of options, and not everything will be covered here.
set positions¶
shift
move_to
align_to
, next_to
,to_corner
, to_edge
, arrange
, arrange_in_grid
[3]:
dORIGIN= Dot(color= BLUE,radius=0.5)
[4]:
%%manim $params
class Example(Scene):
def construct(self):
d= Dot(color= YELLOW, radius=0.5)
d.shift(2*RIGHT)
self.add(dORIGIN, d)

[5]:
%%manim $params
class Example(Scene):
def construct(self):
d= Dot(color= YELLOW, radius=0.5)
d.shift(3*RIGHT+0.8*UP)
self.add(dORIGIN, d)

[6]:
%%manim $params
class Example(Scene):
def construct(self):
d= Dot(color= ORANGE, radius=0.5)
d.next_to(dORIGIN, LEFT)
self.add(dORIGIN, d)

[7]:
%%manim $params
class Example(Scene):
def construct(self):
d= Dot(color= ORANGE, radius=0.5)
d.next_to(dORIGIN, LEFT, buff=0)
self.add(dORIGIN, d)

[8]:
%%manim $params
class Example(Scene):
def construct(self):
d= Dot(color= ORANGE, radius=0.5)
d.next_to(dORIGIN, LEFT, buff=4)
self.add(dORIGIN, d)

[9]:
%%manim $params
class Example(Scene):
def construct(self):
d= Dot(color= ORANGE, radius=0.5)
d.next_to(dORIGIN, UL,buff=-0.5) # UL is UPLEFT
self.add(dORIGIN, d)

[10]:
%%manim $params
class Example(Scene):
def construct(self):
d= Dot(color= ORANGE, radius=0.5)
d.to_edge(LEFT)
self.add(dORIGIN, d)

[11]:
%%manim $params
class Example(Scene):
def construct(self):
s= Star(stroke_width=10)
d=Dot(color= ORANGE, radius=0.5)
d.align_to(s,DOWN)
self.add(s,d)

[12]:
%%manim $params
class Example(Scene):
def construct(self):
s= Star(stroke_width=10)
d=Dot(color= ORANGE, radius=0.5)
d.next_to(s,RIGHT, aligned_edge=UP) #next to and align combined
self.add(s,d)

[13]:
%%manim $params
class Example(Scene):
def construct(self):
for i in range(0,10):
self.add(Dot(color= ORANGE, radius=0.5))
VGroup(*self.mobjects).arrange()

[14]:
%%manim $params
class Example(Scene):
def construct(self):
for i in range(0,24):
self.add(Dot(color= ORANGE, radius=0.2))
VGroup(*self.mobjects).arrange_in_grid(cols=6)

get positions¶
get_center
, get_top
, get_right
, get_start
[15]:
s= Star(stroke_width=10)
d=Dot(color= YELLOW, radius=0.2)
[16]:
%%manim $params
class Example(Scene):
def construct(self):
pos= s.get_center()
self.add(s, d.move_to(pos))

[17]:
%%manim $params
class Example(Scene):
def construct(self):
pos= s.get_center_of_mass()
self.add(s, d.move_to(pos))

[18]:
%%manim $params
class Example(Scene):
def construct(self):
pos= s.get_top()
self.add(s, d.move_to(pos))

[19]:
%%manim $params
class Example(Scene):
def construct(self):
pos= s.get_right()
self.add(s, d.move_to(pos))

[20]:
%%manim $params
class Example(Scene):
def construct(self):
pos= s.get_bottom()
self.add(s, d.move_to(pos))

[21]:
%%manim $params
class Example(Scene):
def construct(self):
pos= s.get_left()
self.add(s, d.move_to(pos))

[22]:
%%manim $params
class Example(Scene):
def construct(self):
pos= s.get_corner(UL)
self.add(s, d.move_to(pos))

[23]:
%%manim $params
class Example(Scene):
def construct(self):
pos= s.get_corner(DR)
self.add(s, d.move_to(pos))

[24]:
arc= Arc(radius=1.0, start_angle=-PI/16, angle=PI, stroke_width=10)
[25]:
%%manim $params
class Example(Scene):
def construct(self):
pos= arc.get_start()
self.add(arc, d.move_to(pos))

[26]:
%%manim $params
class Example(Scene):
def construct(self):
pos= arc.get_end()
self.add(arc, d.move_to(pos))

[27]:
%%manim $params
class Example(Scene):
def construct(self):
pos= arc.get_midpoint()
self.add(arc, d.move_to(pos))

[28]:
%%manim $params
class Example(Scene):
def construct(self):
pos= arc.point_from_proportion(0.2)
self.add(arc, d.move_to(pos))

[29]:
%%manim $params
class Example(Scene):
def construct(self):
pos= arc.get_center()
self.add(arc, d.move_to(pos))

[30]:
%%manim $params
class Example(Scene):
def construct(self):
pos= arc.get_center_of_mass()
self.add(arc, d.move_to(pos))

[31]:
%%manim $params
class Example(Scene):
def construct(self):
pos= arc.get_arc_center()
self.add(arc, d.move_to(pos))

[32]:
%%manim $params
class Example(Scene): #Example for `get_x` , `get_y`, `set_x` and `set_y`
def construct(self):
d = Dot(point=[3,1,0],radius=0.2,color= BLUE)
triangle= Triangle(color=YELLOW, stroke_width=10).scale(0.5)
x_pos=d.get_x()
print(x_pos)
triangle.set_x(x_pos)
self.add(d, triangle)
3.0

[33]:
%%manim $params
class Example(Scene): #Example for `get_x` , `get_y`, `set_x` and `set_y`
def construct(self):
d = Dot(point=[3,1,0],radius=0.2,color= BLUE)
triangle= Triangle(color=YELLOW, stroke_width=10).scale(0.5)
y_pos=d.get_y()
print(y_pos)
triangle.set_y(y_pos)
self.add(d, triangle)
1.0

Scaling and Stretching¶
[34]:
%%manim $params
class Example(Scene):
def construct(self):
d= Dot(color= YELLOW)
d.scale(10)
self.add(d)

[35]:
%%manim $params
class Example(Scene):
def construct(self):
d= Dot(color= YELLOW)
d.scale(10)
d.stretch_in_place(4, dim = 0) # dim = 0 means vertical
self.add(d)

[36]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
d= Dot(color= YELLOW)
d.scale(10)
d.stretch_in_place(2, dim = 1) # dim = 1 means horizontal
self.add(d)

[37]:
%%manim $params
class Example(Scene):
def construct(self):
d= Dot(color= YELLOW)
d.scale(10)
d.apply_matrix([[0.5, 0.5, 0], # shear matrix
[ 0 , 1 , 0],
[ 0 , 0 , 1]])
self.add(d)

Rotating¶
[38]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
m= ManimBanner().scale(0.5)
m.rotate(PI/8)
self.add(m)

[39]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
m= ManimBanner().scale(0.5)
m.rotate(-20*DEGREES)
self.add(m)

[40]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
m= ManimBanner().scale(0.5)
self.add(m.copy())
m.rotate(about_point=2*LEFT, angle=180*DEGREES)
self.add(m, Dot(2*LEFT,radius=0.1))

[41]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
m= ManimBanner().scale(0.5)
m.rotate(axis=UP,angle=60*DEGREES)
self.add(m)

Note
Python is very fertile tool, there multiple ways to accomplish a certain task, but some options are not “best practice”. For the methods in the next chapters, I want to show the best practice (labeled with BEST and the green check with the star), other possible options (labeled with YES and the green check), and options that do not work (labeled with NO and the red cross)
[42]:
# ignore this cell, only for setup
YES = SVGMobject("good.svg").to_edge(LEFT, buff=1)
BEST = YES.copy()
BEST.add(Star(color= YELLOW, fill_opacity=1).scale(0.5).move_to(BEST).shift(0.5*DOWN+0.5*RIGHT))
NO = Cross(Square(), stroke_color = RED_D, stroke_width = 38).scale(0.9).move_to(YES)
Colors and Opacity¶
- Color parameters for Mobjects are
stroke_color
,fill_color
andcolor
. The parametercolor
automatically sets bothstroke_color
andfill_color
.The recommended ways to set colors are viac = Circle(fill_color= BLUE, fill_opacity= 1 )
,c.set_fill(color=RED)
orc.set_style(fill_color=GREEN)
Not possible arec.fill_color=YELLOW
,c.set(fill_color=YELLOW)
andc.set_fill_color(YELLOW)
- Opacity parameters for Mobjects are
fill_opacity
andstroke_opacity
(there is notopacity
here).The recommended ways to set opacity are viac = Circle(fill_color= BLUE, fill_opacity= 0.5 )
,c.set_fill(color=RED)
orc.set_style(fill_color=GREEN)
Analog to colors,c.fill_opacity=1
,c.set(fill_opacity=1)
andc.set_fill_opacity(1)
are not possible. (to keep things short, these examples are not shown).
Colors¶
[43]:
%%manim $params
class Example(Scene):
def construct(self):
c = Square(fill_color= BLUE, fill_opacity= 1 )
self.add(BEST,c)

[44]:
%%manim $params
class Example(Scene):
def construct(self):
c = Square(fill_color= BLUE, fill_opacity= 1)
c.set_fill(color=RED)
self.add(BEST,c)

[45]:
%%manim $params
class Example(Scene):
def construct(self):
c = Square(fill_color= BLUE, fill_opacity= 1)
c.set_style(fill_color=GREEN)
self.add(BEST,c)

[46]:
%%manim $params
class Example(Scene):
def construct(self):
c = Square(fill_opacity= 1)
c.fill_color=YELLOW
self.add(NO,c)

[47]:
%%manim $params
class Example(Scene):
def construct(self):
c = Square(fill_opacity= 1)
c.set(fill_color=YELLOW)
self.add(NO,c)

[48]:
%%manim $params
class Example(Scene):
def construct(self):
c = Square(fill_opacity= 1)
c.set_fill_color(YELLOW)
self.add(NO,c)
<string>:4: DeprecationWarning: This method is not guaranteed to stay around. Please prefer setting the attribute normally or with Mobject.set().

[49]:
%%manim $params
class Example(Scene):
def construct(self):
self.camera.background_color = PURPLE
self.add(BEST)

Opacitiy¶
[50]:
%%manim $params
class Example(Scene):
def construct(self):
c = Ellipse(color= YELLOW, fill_opacity=0.3).scale(2)
self.add(BEST,c)

[51]:
%%manim $params
class Example(Scene):
def construct(self):
c = Ellipse(color= YELLOW).scale(2)
c.set_fill(opacity=0.5) # be careful: here, it must be `opacity` and not `fill_opacity` !
self.add(BEST,c)

[52]:
%%manim $params
class Example(Scene):
def construct(self):
c = Ellipse(color= YELLOW).scale(2)
c.set_style(fill_opacity=0.7) # and here, it must be `fill_opacity` and not `opacity` !
self.add(BEST,c)

Stroke width¶
Circle(stroke_width=30)
, c.set_stroke(width = 30)
or c.set_style(stroke_width= 30)
c.stroke_width = 30
and c.set(stroke_width = 30)
c.set_stroke_width(30)
[53]:
%%manim $params
class Example(Scene):
def construct(self):
c = Circle(stroke_width=30)
self.add(BEST,c)

[54]:
%%manim $params
class Example(Scene):
def construct(self):
c = Circle()
c.set_stroke(width = 30)
self.add(BEST,c)

[55]:
%%manim $params
class Example(Scene):
def construct(self):
c = Circle()
c.set_style(stroke_width= 30)
self.add(BEST,c)

[56]:
%%manim $params
class Example(Scene):
def construct(self):
c = Circle()
c.stroke_width = 30
self.add(YES,c)

[57]:
%%manim $params
class Example(Scene):
def construct(self):
c = Circle()
c.set(stroke_width = 30)
self.add(YES,c)

[58]:
%%manim $params
class Example(Scene):
def construct(self):
c = Circle()
c.set_stroke_width(30)
self.add(NO,c)
<string>:4: DeprecationWarning: This method is not guaranteed to stay around. Please prefer setting the attribute normally or with Mobject.set().

Layers¶
There are two main ways to change the layers of Mobjects:
Reordering the list of submobjects that where added
Using the z_index
submobjects¶
A scene stores displayed mobjects in a list. They are displayed in the order that they are added to the scene with the syntax self.add(circleLeft,circleRight)
First, we have a look on positioning mobjects with self.add
and the methods self.bring_to_back
and self.bring_to_front
. In most cases, this is completely enough. Later, we will come to the z_index, that is seen by manim by one priority higher: Even when a mobject is added first to the mobject list, it will be displayed on
top of the others, if it has a higher z_index. An example about this will be seen later.
[59]:
circleLeft = Circle(color=BLUE, fill_opacity=1)
circleRight = Circle(color=ORANGE,fill_opacity=1).shift(RIGHT)
line = Line(2*LEFT,3*RIGHT,color=YELLOW, stroke_width=20)
[60]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
self.add(circleLeft,circleRight)
self.add(BEST)

[61]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
self.add(circleRight,circleLeft)
self.add(BEST)

[62]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
self.add(circleLeft,circleRight, line)
self.add(BEST)

[63]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
self.add(circleLeft,circleRight, line)
print(self.mobjects)
self.bring_to_back(line)
print(self.mobjects)
self.add(BEST)
[Circle, Circle, Line]
[Line, Circle, Circle]

[64]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
self.add(circleLeft,circleRight, line)
print(self.mobjects)
self.bring_to_front(circleLeft)
print(self.mobjects)
self.add(BEST)
[Circle, Circle, Line]
[Circle, Line, Circle]

z_index¶
triangle = Triangle(z_index=1)
,triangle.z_index=1
, triangle.set(z_index=1)
and triangle.set_z_index(1)
triangle.set_style(z_index=1)
[65]:
#initilizing line,circle,square and triangle
BUFF= 0.5*DOWN
line = Line(3*LEFT,3*RIGHT,color=YELLOW, stroke_width=20)
circle = Circle(color=GREEN_D, fill_opacity=1).shift(LEFT+BUFF)
square = Square(color=BLUE_D, fill_opacity=1).shift(UP+BUFF)
triangle = Triangle(color=RED_D, fill_opacity=1).shift(RIGHT+BUFF)
[66]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
self.add(line,triangle, square, circle) # order matters
print(self.mobjects)
print(f"{triangle.z_index=} , {square.z_index=} , {circle.z_index=} , {line.z_index=}")
self.add(BEST)
[Line, Triangle, Square, Circle]
triangle.z_index=0 , square.z_index=0 , circle.z_index=0 , line.z_index=0

[67]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
triangle.z_index=1
self.add(triangle, square, circle,line) # order matters
print(self.mobjects)
print(f"{triangle.z_index=} , {square.z_index=} , {circle.z_index=} , {line.z_index=}")
self.add(BEST)
[Triangle, Square, Circle, Line]
triangle.z_index=1 , square.z_index=0 , circle.z_index=0 , line.z_index=0

[68]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
triangle.z_index = 1
square.z_index = 2
circle.z_index = 3
self.add(triangle, square, circle,line) # order matters
self.add(BEST)
print(f"{line.z_index=}")
line.z_index=0

[69]:
%%manim $paramsbigger
class Example(Scene):
def construct(self):
triangle.z_index = 3
square.z_index = 2
circle.z_index = 1
self.add(triangle, square, circle,line) # order matters
self.add(BEST)
print(f"{line.z_index=}")
line.z_index=0

[70]:
%%manim $paramsbigger
triangle.z_index = 0
square.z_index = 0
circle.z_index = 0
class Example(Scene):
def construct(self):
triangle.set(z_index=1)
self.add(triangle, square, circle,line) # order matters
print(self.mobjects)
print(f"{triangle.z_index=} , {square.z_index=} , {circle.z_index=} , {line.z_index=}")
self.add(BEST)
[Triangle, Square, Circle, Line]
triangle.z_index=1 , square.z_index=0 , circle.z_index=0 , line.z_index=0

[71]:
%%manim $paramsbigger
triangle.z_index = 0
square.z_index = 0
circle.z_index = 0
class Example(Scene):
def construct(self):
try:
triangle.set_style(z_index=1) # here we expect an error! Only for didactic purpose, it is put into this `try` blog, so that no long error message is shown.
except TypeError:
print("TypeError, set_style() got an unexpected keyword argument 'z_index'. ")
self.add(NO)
self.add(triangle, square, circle,line) # order matters
print(f"{triangle.z_index=} , {square.z_index=} , {circle.z_index=} , {line.z_index=}")
TypeError, set_style() got an unexpected keyword argument 'z_index'.
triangle.z_index=0 , square.z_index=0 , circle.z_index=0 , line.z_index=0

VGroup and Group¶
VGroup¶
It is a Group of VMobjects (“V” stands for Vector)
[72]:
#only for setup
def create_dots():
blue1_ref= Dot(color= BLUE, point=[-.3,-.5,0], radius=0.5)
blue2_ref= Dot(color= BLUE_A, point=[ .3,-.5,0], radius=0.5)
yellow1_ref= Dot(color= YELLOW, point=[-.3, .5,0], radius=0.5)
yellow2_ref= Dot(color= YELLOW_A, point=[ .3, .5,0], radius=0.5)
return blue1_ref, blue2_ref,yellow1_ref,yellow2_ref
[73]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene):
def construct(self):
self.add(blue1,blue2, yellow1,yellow2)

[74]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene):
def construct(self):
VGroup(yellow1,yellow2).shift(RIGHT)
self.add(blue1,blue2, yellow1,yellow2)

[75]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene):
def construct(self):
g1=VGroup(yellow1,yellow2).shift(2*RIGHT)
self.add(blue1,blue2, g1)

[76]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene):
def construct(self):
g1=VGroup(yellow1,yellow2).set_color(RED)
self.add(blue1,blue2, g1)

[77]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene):
def construct(self):
g1=VGroup(yellow1,yellow2).shift(0.5*DOWN)
g2=VGroup(blue1,blue2)
self.add(g1, g2)

[78]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene):
def construct(self):
g1=VGroup(yellow1,yellow2).shift(0.5*DOWN)
g2=VGroup(blue1,blue2)
self.add(g2,g1)

[79]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene): # Groups of Groups
def construct(self):
g1=VGroup(yellow1,yellow2).shift(0.5*DOWN)
g2=VGroup(blue1,blue2)
gAll = VGroup(g1, g2)
self.add(gAll)
print(gAll.submobjects)
print(gAll.submobjects[0].submobjects)
print(gAll.submobjects[1].submobjects)
[VGroup(Dot, Dot), VGroup(Dot, Dot)]
[Dot, Dot]
[Dot, Dot]

[80]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene): #setting VMobject attibutes
def construct(self):
g=VGroup(yellow1,yellow2,blue1,blue2)
g.set_stroke(color=PURPLE_D, width=20) # <--
self.add(g)

[81]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene): # add syntax
def construct(self):
g=VGroup(yellow1,yellow2,blue1)
g.add(blue2) # <--
g.set_stroke(color=GREEN, width=20)
self.add(g)

[82]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene): # += Syntax
def construct(self):
g=VGroup(yellow1,yellow2,blue1)
g += blue2 # <--
g.set_stroke(color=ORANGE, width=20)
self.add(g)

[83]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene): # empty initilizing
def construct(self):
g=VGroup()
for _ in range(0,10):
g += yellow1.copy()
g.set_stroke(color=WHITE, width=20)
g.arrange_in_grid(rows=2) # <-- Groups and VGroups can be arranged in grids
g.move_to(ORIGIN)
self.add(g)

Note:
VMobject().add(…) is functionally equivalent to VGroup(…), but it is recommended to use VGroup, as
It is better readable
supports the
+=
syntax
[84]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene): # using VMobject instead
def construct(self):
g= VMobject()
g.add(yellow1,yellow2,blue1,blue2)
g.set_stroke(color=PURPLE_D, width=20)
self.add(g)

[85]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene): # other Mobjects can be added to any Mobjects
def construct(self):
d= Dot(color= YELLOW, radius=0.7)
d.add(Line(0.2*UP, 0.8*UP, color=RED,stroke_width=40))
self.add(d)

[86]:
%%manim $params
dot= Dot(color= YELLOW, radius=0.5)
image = ImageMobject(np.uint8([[200, 233, 111, 200],
[255, 100, 190, 100]])).shift(2*RIGHT)
image.height = 1
class Example(Scene):
def construct(self):
self.add(dot, image)
try: # Image is not a VMobject!
VGroup(dot,image).shift(3*RIGHT)
except TypeError:
print("Adding an Mobject to a VGroup is not possible!")
self.add(NO)
Adding an Mobject to a VGroup is not possible!

Group¶
Groups Mobjects and VMobjects togehter. You can only use the methods of Mobject here. Methods of VMobject wont be supported.
[87]:
%%manim $params
dot= Dot(color= YELLOW, radius=0.5)
image = ImageMobject(np.uint8([[200, 233, 111, 200],
[255, 100, 190, 100]])).shift(2*RIGHT)
image.height = 1
class Example(Scene):
def construct(self):
self.add(dot, image)
Group(dot,image).shift(3*RIGHT)

[88]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene): #
def construct(self):
g=Group(yellow1,yellow2,blue1,blue2)
try:
g.set_stroke(color=PURPLE_D, width=20)
except TypeError:
print("TypeError!")
self.add(NO)
self.add(g)
TypeError!

Note: z_index
is not supported, neither for VGroup nor for Group
[89]:
%%manim $params
blue1,blue2, yellow1,yellow2 = create_dots()
class Example(Scene):
def construct(self):
a=VGroup(yellow1,yellow2).shift(0.5*DOWN)
b=VGroup(blue1,blue2)
a.set_z_index(2)
b.set_z_index(1)
self.add(a,b)
self.add(NO)

Congratulations!
You are now a master in setting up your Mobjects on a scene. Let’s go on with the part you came to manim for in the first place: Animations!
Chapter 3 - Animations¶
Latest update : 13.6.2021
There are a wide range of possibilities to animate your mobjects that all work a bit differently. Here is a broad overview so that you can choose the animation stategy that fits best for your project. This chapter will cover ValueTrackers
, Updaters
, self.play Transformations
the mobject.animate
syntax and mobject.become
syntax.
[1]:
from manim import *
Manim Community v0.8.0
[2]:
#ignore this cell, only for setup
params= "-v WARNING --progress_bar None -r 500,200 --disable_caching Example"
NO = Cross(Square(), stroke_color = RED_D, stroke_width = 38).scale(0.9).to_edge(LEFT, buff=1)
YES = SVGMobject("good.svg").to_edge(LEFT, buff=1)
BEST = YES.copy()
BEST.add(Star(color= YELLOW, fill_opacity=1).scale(0.5).move_to(BEST).shift(0.5*DOWN+0.5*RIGHT));
Simple Replacements¶
[3]:
%%manim $params
class Example(Scene):
def construct(self):
dot= Dot(color= YELLOW, radius=0.5)
self.add(dot)
self.wait()
dot.scale(2)
self.wait()
dot.scale(2)
self.wait(2)
[4]:
%%manim $params
class Example(Scene):
def construct(self):
dot= Dot(color= YELLOW, radius=0.5)
square= Square(side_length=4,color= BLUE, fill_opacity=1)
triangle= Triangle(radius=3,color= ORANGE, fill_opacity=1).shift(DOWN*0.5)
self.add(dot)
self.wait()
dot.become(square)
self.wait()
dot.become(triangle)
self.wait()
Using .animate Syntax¶
[5]:
%%manim $params
class Example(Scene):
def construct(self):
dot= Dot(color= YELLOW, radius=0.5)
self.play(dot.animate.scale(2))
[6]:
%%manim $params
class Example(Scene):
def construct(self):
dot= Dot(color= YELLOW, radius=0.5)
self.play(dot.animate.shift(2*RIGHT))
[7]:
%%manim $params
class Example(Scene):
def construct(self):
dot= Dot(color= YELLOW, radius=0.5)
self.play(dot.animate.set_color(BLUE))
[8]:
%%manim $params
class Example(Scene):
def construct(self):
dot= Dot(color= YELLOW, radius=0.5)
self.play(dot.animate.shift(2*RIGHT).scale(2))
[9]:
%%manim $params
class Example(Scene):
def construct(self):
dot= Dot(color= YELLOW, radius=0.5)
self.play(dot.animate.shift(2*RIGHT).scale(2).set_color(BLUE))
Updaters¶
They are very diverse! And they can be used with and without a “dt” parameter
[10]:
%%manim $params
class Example(Scene):
def construct(self):
dot = Dot(color= GREEN, radius=0.7)
self.add(dot)
def foo(mob,dt):
mob.shift(2*RIGHT*dt)
dot.add_updater(foo)
self.wait(3)
[11]:
%%manim $params
class Example(Scene):
def construct(self):
dot = Dot(color= GREEN, radius=0.7)
self.add(dot)
dot.add_updater(lambda x,dt: x.shift(2*RIGHT*dt))
self.wait(3)
[12]:
%%manim $params
class Example(Scene): # when there is no dt parameter, the updater does not work
def construct(self):
dot = Dot(color= GREEN, radius=0.7)
self.add(dot,NO)
dot.add_updater(lambda x : x.shift(2*RIGHT*0.1))
self.wait(3)
Note: Not using the “dt” parameter will make your animation framerate dependent, but this can be solved using ValueTracker, which can be seen in the next section
Updaters + ValueTrackers¶
[13]:
%%manim $params
class Example(Scene):
def construct(self):
tracker= ValueTracker(0)
dot = Dot(color= GREEN, radius=0.7)
self.add(dot)
def foo(mob):
mob.move_to(RIGHT*tracker.get_value())
dot.add_updater(foo)
self.play(tracker.animate.set_value(2), rate_func= linear)
Note: now you can also use rate functions:
[14]:
%%manim $params
class Example(Scene):
def construct(self):
tracker= ValueTracker(0)
dot = Dot(color= GREEN, radius=0.7)
self.add(dot)
def foo(mob):
mob.move_to(RIGHT*tracker.get_value())
dot.add_updater(foo)
self.play(tracker.animate.set_value(2), rate_func= smooth)
[15]:
%%manim $params
class Example(Scene):
def construct(self):
tracker= ValueTracker(0.5)
dot = Dot(color= GREEN, radius=0.7)
self.add(dot)
def foo(mob):
mob.move_to(RIGHT*tracker.get_value())
dot.add_updater(foo)
self.play(tracker.animate.set_value(2.2), rate_func= smooth)
self.play(tracker.animate.increment_value(1), rate_func= smooth)
self.play(tracker.animate.increment_value(-1), rate_func= smooth)
self.play(tracker.animate.set_value(0.5), rate_func= linear)
[16]:
%%manim $params
#one can now also add additional properties to mobjects, in this case a counter.
class Example(Scene):
def construct(self):
tracker= ValueTracker(0)
dot = Dot(color= GREEN, radius=0.7)
self.add(dot)
dot.counter=0
def foo(mob):
mob.move_to(RIGHT*tracker.get_value())
if mob.counter == 20:
mob.set_color(random_bright_color())
mob.counter = 0
mob.counter += 1
dot.add_updater(foo)
self.play(tracker.animate.set_value(2), rate_func= linear, run_time=3)
Transformations¶
[17]:
%%manim $params
class Example(Scene):
def construct(self):
d= Dot(color= YELLOW, radius=0.5)
d2= d.copy().shift(2*RIGHT)
self.play(Transform(d, d2))
Does and Donts¶
Note that when you choose to work with updaters, your script might depend on the frame rate.
[18]:
%%manim $params
class Example(Scene):
def construct(self):
print(f"{config.frame_rate = }fps")
dotred= Dot(color= RED, radius=0.5).shift(UP)
dotgreen = Dot(color= GREEN, radius=0.5)
dotgreen.next_to(dotred,DOWN)
self.add(dotgreen,dotred)
DIR= 2*RIGHT
dotgreen.add_updater(lambda x,dt: x.shift(DIR*dt))
dotred.add_updater(lambda x,dt: x.shift(DIR*1/60))
self.wait(3)
config.frame_rate = 60fps
[19]:
params5fps = "-v WARNING --progress_bar None --frame_rate=5 -r 500,200 --disable_caching Example"
[20]:
%%manim $params5fps
class Example(Scene):
def construct(self):
print(f"{config.frame_rate = }fps")
dotred= Dot(color= RED, radius=0.5).shift(UP)
dotgreen = Dot(color= GREEN, radius=0.5)
dotgreen.next_to(dotred,DOWN)
self.add(dotgreen,dotred)
DIR= 2*RIGHT
dotgreen.add_updater(lambda x,dt: x.shift(DIR*dt))
dotred.add_updater(lambda x,dt: x.shift(DIR*1/60))
self.wait(3)
config.frame_rate = 5.0fps
Rotation animation¶
There are multiple ways to rotate a square, but not all will result in that animation that you might have expected.
[21]:
%%manim $params
class Example(Scene):
def construct(self, **kwargs):
s1= Square().set_color(YELLOW)
self.add(s1, BEST)
self.play(Rotate(s1, angle=PI/2))
[22]:
%%manim $params
class Example(Scene):
def construct(self, **kwargs):
s2= Square().set_color(PURPLE)
self.add(s2, NO)
self.play(s2.animate.rotate(PI/2))
[23]:
%%manim $params
class Example(Scene):
def construct(self, **kwargs):
theta_track= ValueTracker(0)
s3= Square().set_color(ORANGE)
self.add(s3, YES)
s3.previous_angle=0
def pref(x):
x.previous_angle=theta_track.get_value()
s3.add_updater(lambda x: x.rotate(theta_track.get_value()-s3.previous_angle))
s3.add_updater(pref)
self.play(theta_track.animate.increment_value(PI/2))
[24]:
#not yet implemented
#class Example(Scene):
# def construct(self, **kwargs):
#s3b= Square().set_color(YELLOW)
#self.add(s3b)
#theta_track= DeltaValueTracker(0)
#s3b.add_updater(lambda x: x.rotate(theta_track.get_delta_value()))
#self.play(theta_track.animate.set_value(90*DEGREES))
[25]:
%%manim $params
# NOT WORKING!, BAD PRACTICE.
class Example(Scene):
def construct(self, **kwargs):
s4= Square().set_color(GREEN)
self.add(s4, NO)
theta_track= ValueTracker(0)
s4.add_updater(lambda x: x.rotate(theta_track.get_value()))
self.play(theta_track.animate.increment_value(PI/2))
[26]:
%%manim $params
class Example(Scene):
def construct(self, **kwargs):
s6= Square().set_color(PINK)
self.add(s6, YES)
s6.add_updater(lambda x, dt: x.rotate(dt*PI/2))
self.wait(1)
Known bugs¶
Bug with updaters that do not have a dt¶
[27]:
%%manim $params
class Example(Scene):
def construct(self):
dot = Dot(color= GREEN, radius=0.7)
self.add(dot,NO)
#dot.add_updater(lambda x,dt : x)
dot.add_updater(lambda x : x.shift(2*RIGHT*1/config.frame_rate))
self.wait(3)
[28]:
%%manim $params
class Example(Scene):
def construct(self):
dot = Dot(color= GREEN, radius=0.7)
self.add(dot,YES)
dot.add_updater(lambda x,dt : x) #adding this line will make the updater continiously watch
dot.add_updater(lambda x : x.shift(2*RIGHT*1/config.frame_rate))
self.wait(3)
Bugs with updater in ZoomedScene¶
[29]:
%%manim $params
class Example(ZoomedScene):
def __init__(self, **kwargs):
ZoomedScene.__init__(
self,
zoom_factor=0.3,
zoomed_display_height=4,
zoomed_display_width=4,
image_frame_stroke_width=20,
zoomed_camera_config={
"default_frame_stroke_width": 3,
},
**kwargs
)
def construct(self):
d= Dot()
self.add(d)
imgo =Square().scale(0.3).set_color(RED)
self.add(imgo)
#imgo.add_updater(lambda x: x) # COMMENTED OUT
self.activate_zooming(animate=True)
self.play(self.zoomed_camera.frame.animate.shift(0.5 * (LEFT+UP*0.8)))
self.play(self.zoomed_camera.frame.animate.shift(0.5 * (RIGHT+DOWN*2.8)))
[30]:
%%manim $params
class Example(ZoomedScene):
def __init__(self, **kwargs):
ZoomedScene.__init__(
self,
zoom_factor=0.3,
zoomed_display_height=4,
zoomed_display_width=4,
image_frame_stroke_width=20,
zoomed_camera_config={
"default_frame_stroke_width": 3,
},
**kwargs
)
def construct(self):
d= Dot()
self.add(d)
imgo =Square().scale(0.3).set_color(RED)
self.add(imgo)
imgo.add_updater(lambda x: x) # INCLUDED
self.activate_zooming(animate=True)
self.play(self.zoomed_camera.frame.animate.shift(0.5 * (LEFT+UP*0.8)))
self.play(self.zoomed_camera.frame.animate.shift(0.5 * (RIGHT+DOWN*2.8)))
[ ]:
(Chapter 4 - Building Scenes)¶
Scenes in manim can become cluttered very easily. As you want to have videos in the end, and not the code, code tidyness is not crucial, but often it is useful to stay organized and to not get lost in complex scenes.
More comming soon!¶
[ ]:
Chapter 5 - Resolution and Camera¶
[1]:
from manim import *
Manim Community v0.8.0
Scene Coordinates¶
[2]:
config.frame_width/config.frame_height
[2]:
1.7777777777777777
[3]:
config.pixel_width/config.pixel_height
[3]:
1.7777777777777777
[4]:
16/9
[4]:
1.7777777777777777
[5]:
# for setup only
def yellow_frame_annotation(framew, frameh):
d1 = DoubleArrow(framew * LEFT / 2, framew * RIGHT / 2, buff=0).to_edge(DOWN)
t1 = Text(str(framew)[:6]).next_to(d1, UP)
d2 = DoubleArrow(frameh * UP / 2, frameh * DOWN / 2, buff=0).to_edge(LEFT)
t2= Text(str(frameh)).next_to(d2, RIGHT)
x=Group(d1,d2,t1,t2).set_color(YELLOW)
return x
def blue_pixel_annotation(framew, frameh,pixelw, pixelh):
d1 = DoubleArrow(framew * LEFT / 2, framew * RIGHT / 2, buff=0).to_edge(UP)
t1 = Text(str(pixelw) + " pixel").next_to(d1, DOWN)
d2 = DoubleArrow(frameh * UP / 2, frameh * DOWN / 2, buff=0).to_edge(RIGHT)
t2= Text(str(pixelh) + " pixel").next_to(d2, LEFT)
x=Group(d1,d2,t1,t2).set_color(BLUE)
return x
annulus = Annulus(inner_radius =1,outer_radius=2,color=WHITE, stroke_width=10)
Pixel Ratio of 16/9¶
See a table of commen 16/9 resolutions here: https://en.wikipedia.org/wiki/16:9_aspect_ratio#Common_resolutions
[6]:
%%manim -v WARNING -s -r 160,90 --disable_caching Example
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

[7]:
%%manim -v WARNING -s -r 256,144 --disable_caching Example
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

[8]:
%%manim -v WARNING -s -ql --disable_caching Example
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

[9]:
%%manim -v WARNING -s -qm --disable_caching Example
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

Note
[10]:
%%manim -v WARNING -s -qh --disable_caching Example
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

Pixel Ratio Unequal to 16/9¶
When the pixel ratio is heigher then 16/9 frame_height cropped.
When the pixel ratio is lower then 16/9 frame_height padded.
[11]:
%%manim -v WARNING -s -r 1000,500 --disable_caching Example
#ratio of 2/1
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

[12]:
%%manim -v WARNING -s -r 1000,50 --disable_caching Example
#ratio of 20/1
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

[13]:
%%manim -v WARNING -s -r 500,1000 --disable_caching Example
#ratio of 1/2
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

Changing the frame_width¶
Increasing the value
config.frame_width
will zoom out the MobjectDecreasing the value
config.frame_width
will zoom in the Mobject
Note: The frame_height is adjusted accordingly. Note 2: I do not recommend to change the frame width with config.frame_width, better use the self.camera.frame.set(...)
syntax shown in the next section.
[14]:
%%manim -v WARNING -s -ql --disable_caching Example
config.frame_width =30
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

[15]:
%%manim -v WARNING -s -ql --disable_caching Example
config.frame_width =13
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

[16]:
%%manim -v WARNING -s -ql --disable_caching Example
config.frame_width =14.22222
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

Note
Changing config.frame_height
has no effect on the Mobjects displaied on the screen.
[17]:
%%manim -v WARNING -s -ql --disable_caching Example
config.frame_height =42
class Example(Scene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
pixel_annotation= blue_pixel_annotation(config.frame_width,config.frame_height,config.pixel_width,config.pixel_height)
self.add(frame_annotation, pixel_annotation, annulus)

[18]:
config.frame_height =8 # resetting the frame_height value to default
Camera Scene¶
[19]:
%%manim -v WARNING -s -ql --disable_caching Example
class Example(MovingCameraScene):
def construct(self):
self.camera.frame.set(width=20)
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
self.add(FullScreenRectangle(color=RED, stroke_width=40))
self.add(frame_annotation, annulus)

[20]:
%%manim -v WARNING -s -ql --disable_caching Example
class Example(MovingCameraScene):
def construct(self):
self.camera.frame.set(width=40)
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
self.add(FullScreenRectangle(color=RED, stroke_width=40))
self.add(frame_annotation, annulus)

[21]:
%%manim -v WARNING -s -ql --disable_caching Example
class Example(MovingCameraScene):
def construct(self):
self.camera.frame.shift(2*DOWN+2*LEFT)
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
self.add(FullScreenRectangle(color=RED, stroke_width=40))
self.add(frame_annotation, annulus)

[22]:
%%manim -v WARNING -s -ql --disable_caching Example
class Example(MovingCameraScene):
def construct(self):
self.camera.frame.shift(4*DOWN+4*LEFT)
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
self.add(FullScreenRectangle(color=RED, stroke_width=40))
self.add(frame_annotation, annulus)

[23]:
%%manim -v WARNING -ql --disable_caching Example
class Example(MovingCameraScene):
def construct(self):
frame_annotation= yellow_frame_annotation(config.frame_width,config.frame_height)
self.add(FullScreenRectangle(color=RED, stroke_width=40))
self.add(frame_annotation, annulus)
self.play(self.camera.frame.animate.shift(UP+2*LEFT).set(width=20))
self.play(self.camera.frame.animate.shift(2*DOWN+4*RIGHT))
self.play(self.camera.frame.animate.move_to(ORIGIN).set(width=14.222))
Chapter 6 - Color Wheel Tutorial¶
Latest update : 13.6.2021
In this notebook, you will learn how to create a color picker with a moving wheel in manim (scroll to the end to see the result)
[1]:
from manim import *
from PIL import Image
import colorsys
import math
#from manim.utils.color import Colors
from colorutils import hsv_to_hex,hex_to_hsv
Manim Community v0.8.0
[2]:
size=490
im = Image.new("RGB", (size,size))
radius = min(im.size)/2.0
cx, cy = im.size[0]/2, im.size[1]/2
pix = im.load()
for x in range(im.width):
for y in range(im.height):
rx = x - cx
ry = y - cy
s = (rx ** 2.0 + ry ** 2.0) ** 0.5 / radius
if s <= 1.0:
h = ((math.atan2(ry, rx) / math.pi) + 1.0) / 2.0
rgb = colorsys.hsv_to_rgb(h, s, 1)
pix[x,y] = tuple([int(round(c*255.0)) for c in rgb])
hsv_hue_sat = im
display(hsv_hue_sat)

[3]:
im = Image.new("RGB", (size,size))
radius = min(im.size)/2.0
cx, cy = im.size[0]/2, im.size[1]/2
pix = im.load()
for x in range(im.width):
for y in range(im.height):
rx = x - cx
ry = y - cy
s = (rx ** 2.0 + ry ** 2.0) ** 0.5 / radius
if s <= 1.0:
h = ((math.atan2(ry, rx) / math.pi) + 1.0) / 2.0
rgb = colorsys.hsv_to_rgb(0, s, 1 )
rgb = [np.mean(rgb)]*3
pix[x,y] = tuple([int(255-round(c*255.0)) for c in rgb])
hsv_value = im
display(hsv_value)

[4]:
class ColorWheels(Group):
def __init__(self, **kwargs):
Group.__init__(self, **kwargs)
im_hue = ImageMobject(hsv_hue_sat).set_z_index(-5)
im_val = ImageMobject(hsv_value).set_z_index(-5)
# im_hue = Circle(radius=1.5).set_style(fill_color=WHITE, fill_opacity=1).set_z_index(-5)
# im_val = Circle(radius=1.5).set_style(fill_color=WHITE, fill_opacity=1).set_z_index(-5)
self.radius = im_hue.height/2
self.add(im_hue, im_val)
Group(*self.submobjects).arrange(DOWN, SMALL_BUFF*1.3).to_edge(RIGHT)
t1= Text("Hue and Saturation").scale(0.3)
t1.next_to(im_hue, UP, buff=SMALL_BUFF).rotate(35*DEGREES, about_point=im_hue.get_center())
self.add(t1)
t2= Text("Value").scale(0.3)
t2.next_to(im_val, UP, buff=SMALL_BUFF).rotate(35*DEGREES, about_point=im_val.get_center())
self.add(t2)
global CENTER_HUE , CENTER_VAL
CENTER_HUE = im_hue.get_center()
CENTER_VAL = im_val.get_center()
[5]:
class HueValSlider(Group):
def __init__(self, wheels, h, s, v,**kwargs):
hue_tracker= ValueTracker(h)
sat_tracker= ValueTracker(s)
val_tracker= ValueTracker(v)
self.hue_tracker= hue_tracker
self.sat_tracker= sat_tracker
self.val_tracker= val_tracker
Group.__init__(self, **kwargs)
hue_dot = Dot(CENTER_HUE+LEFT).set_color(BLACK).scale(0.8).set_z_index(1)
hue_line = Line(CENTER_HUE, hue_dot.get_center()).set_color(BLACK).set_stroke(width=2)
self.hue_line =hue_line
hue_circ= Circle().set_color(BLACK).scale(0.08).move_to(hue_dot.get_center())
hue_dot.add_updater(lambda x: x.move_to(CENTER_HUE+wheels.radius*sat_tracker.get_value()* np.array([-np.cos(hue_tracker.get_value()*DEGREES),np.sin(hue_tracker.get_value()*DEGREES),0])))
hue_dot.add_updater(lambda x: x.set_color(hsv_to_hex((hue_tracker.get_value()%360, sat_tracker.get_value(),val_tracker.get_value()))))
hue_line.add_updater(lambda x: x.put_start_and_end_on(CENTER_HUE, hue_dot.get_center()))
hue_circ.add_updater(lambda x: x.move_to(hue_dot.get_center()))
self.add(hue_dot, hue_circ, hue_line)
val_dot = Dot(CENTER_VAL+LEFT).set_color(BLACK).scale(0.8).set_z_index(1)
val_line = Line(CENTER_VAL, val_dot.get_center()).set_color(BLACK).set_stroke(width=2)
val_circ= Circle().set_color(BLACK).scale(0.08).move_to(val_dot.get_center())
val_dot.add_updater(lambda x: x.move_to(CENTER_VAL+wheels.radius*val_tracker.get_value()* np.array([-np.cos(hue_tracker.get_value()*DEGREES),np.sin(hue_tracker.get_value()*DEGREES),0])))
val_dot.add_updater(lambda x: x.set_color(hsv_to_hex((hue_tracker.get_value()%360, sat_tracker.get_value(),val_tracker.get_value()))))
val_line.add_updater(lambda x: x.put_start_and_end_on(CENTER_VAL, val_dot.get_center()))
val_circ.add_updater(lambda x: x.move_to(val_dot.get_center()))
self.add(val_dot, val_circ, val_line)
[6]:
%%manim -v WARNING -qm --disable_caching Idea3
class Idea3(Scene):
def construct(self):
wheels = ColorWheels()
self.add(wheels)
t1= Dot().scale(4)
t2= Dot().scale(4)
t3 = Dot().scale(4)
gr = VGroup(t1,t2,t3).arrange(DOWN)
self.add(gr)
t1.add_updater(lambda x: x.set_color(hsv_to_hex((huevals1.hue_tracker.get_value()%360, huevals1.sat_tracker.get_value(),1))))
t2.add_updater(lambda x: x.set_color(hsv_to_hex((huevals2.hue_tracker.get_value()%360, huevals2.sat_tracker.get_value(),1))))
t3.add_updater(lambda x: x.set_color(hsv_to_hex((huevals3.hue_tracker.get_value()%360, huevals3.sat_tracker.get_value(),1))))
huevals1=HueValSlider(wheels,0,1,1)
huevals2=HueValSlider(wheels,120,1,1)
huevals3=HueValSlider(wheels,240,1,1)
self.add(huevals1)
self.add(huevals2)
self.add(huevals3)
hues_all_tracker = ValueTracker(0)
self.add(hues_all_tracker)
self.add(huevals1.hue_tracker)
self.add(huevals2.hue_tracker)
self.add(huevals3.hue_tracker)
huevals1.hue_tracker.add_updater(lambda mobject, dt: mobject.increment_value(dt*30))
huevals2.hue_tracker.add_updater(lambda mobject, dt: mobject.increment_value(dt*30))
huevals3.hue_tracker.add_updater(lambda mobject, dt: mobject.increment_value(dt*30))
self.wait(3)
self.play(
huevals1.sat_tracker.animate.increment_value(-0.2),
huevals2.sat_tracker.animate.increment_value(-0.2),
huevals3.sat_tracker.animate.increment_value(-0.2),
)
self.wait(1)
self.play(
huevals1.val_tracker.animate.increment_value(-0.2),
huevals2.val_tracker.animate.increment_value(-0.2),
huevals3.val_tracker.animate.increment_value(-0.2),
)
self.wait(1)
Chapter 7 - Additional Tools¶
Latest update : 13.6.2021
Extracting frames (FFMPEG)¶
In a video edior for post-processing, you might want to have the first frame as an image. This can be achieved with the following script, which will batch-process all videos in the Downloads folder and extract all first frames to the folder “Downloads/processed”
[1]:
from pathlib import Path
import os
suffix = ".mp4"
input_path= Path.home() / "Downloads/"
file_paths= [subp for subp in input_path.rglob('*') if suffix == subp.suffix]
if len(file_paths) == 0:
raise ValueError("No videos in folder")
file_paths.sort()
print(file_paths)
output_path = Path.home() / "Downloads/processed"
output_path.mkdir(parents=True, exist_ok=True)
print(output_path)
for file_p in file_paths:
input = str(file_p)
output = str( output_path / file_p.name)
output = output[:-4] # delete the ending
print(output)
command = f"ffmpeg -i {input} -vframes 1 {output}.png"
os.system(command)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/tmp/ipykernel_2663/4206570128.py in <module>
5 file_paths= [subp for subp in input_path.rglob('*') if suffix == subp.suffix]
6 if len(file_paths) == 0:
----> 7 raise ValueError("No videos in folder")
8 file_paths.sort()
9 print(file_paths)
ValueError: No videos in folder
(TL;DR CheatSheet)¶
[1]:
from manim import *
param = "-v WARNING -s -ql --disable_caching --progress_bar None Example"
paramH = "-v WARNING -s -qh --disable_caching --progress_bar None Example"
paramp = "-v WARNING -ql --disable_caching --progress_bar None Example"
parampH = "-v WARNING -qh --disable_caching --progress_bar None Example"
Manim Community v0.8.0
[2]:
%%manim $param
class Example(Scene):
def construct(self):
self.add(Dot())

[3]:
!manim render --help
Manim Community v0.8.0
Usage: manim render [OPTIONS] FILE [SCENE_NAMES]...
Render SCENE(S) from the input FILE.
FILE is the file path of the script.
SCENES is an optional list of scenes in the file.
Global options:
-c, --config_file TEXT Specify the configuration file to use for
render settings.
--custom_folders Use the folders defined in the
[custom_folders] section of the config file
to define the output folder structure.
--disable_caching Disable the use of the cache (still
generates cache files).
--flush_cache Remove cached partial movie files.
--tex_template TEXT Specify a custom TeX template file.
-v, --verbosity [DEBUG|INFO|WARNING|ERROR|CRITICAL]
Verbosity of CLI output. Changes ffmpeg log
level unless 5+.
--notify_outdated_version / --silent
Display warnings for outdated installation.
--enable_gui Enable GUI interaction.
--gui_location TEXT Starting location for the GUI.
--fullscreen Expand the window to its maximum possible
size.
Output options:
-o, --output_file TEXT Specify the filename(s) of the rendered
scene(s).
--write_to_movie Write to a file.
--media_dir PATH Path to store rendered videos and latex.
--log_dir PATH Path to store render logs.
--log_to_file Log terminal output to file.
Render Options:
-n, --from_animation_number TEXT
Start rendering from n_0 until n_1. If n_1
is left unspecified, renders all scenes
after n_0.
-a, --write_all Render all scenes in the input file.
--format [png|gif|mp4|webm|mov]
-s, --save_last_frame
-q, --quality [l|m|h|p|k] Render quality at the follow resolution
framerates, respectively: 854x480 30FPS,
1280x720 30FPS, 1920x1080 60FPS, 2560x1440
60FPS, 3840x2160 60FPS
-r, --resolution TEXT Resolution in (W,H) for when 16:9 aspect
ratio isn't possible.
--fps, --frame_rate FLOAT Render at this frame rate.
--renderer [cairo|opengl|webgl]
Select a renderer for your Scene.
--use_opengl_renderer Render scenes using OpenGL (Deprecated).
--use_webgl_renderer Render scenes using the WebGL frontend
(Deprecated).
--webgl_renderer_path PATH The path to the WebGL frontend.
-g, --save_pngs Save each frame as png (Deprecated).
-i, --save_as_gif Save as a gif (Deprecated).
-s, --save_last_frame Save last frame as png (Deprecated).
-t, --transparent Render scenes with alpha channel.
--use_projection_fill_shaders Use shaders for OpenGLVMobject fill which
are compatible with transformation matrices.
--use_projection_stroke_shaders
Use shaders for OpenGLVMobject stroke which
are compatible with transformation matrices.
Ease of access options:
--progress_bar [display|leave|none]
Display progress bars and/or keep them
displayed. [default: display]
-p, --preview Preview the Scene's animation. OpenGL does a
live preview in a popup window. Cairo opens
the rendered video file in the system
default media player.
-f, --show_in_file_browser Show the output file in the file browser.
--jupyter Using jupyter notebook magic.
Other options:
--help Show this message and exit.
Made with <3 by Manim Community developers.