Manim
Manim is a python library for programming images or video. It finds appeal among science communicators as it can be used to make high-quality graphics. I consider many well-made Manim graphics to be borderline art.
Manim started as a personal project of Grant Sanderson for creating 3Blue1Brown ↗ videos and later spawned a community that created Manim community edition ↗. It is perhaps the best way to convert mathematics to video. To use this tool to create a good video one needs a field expertise and some knowledge of programming.
In this post, we introduce Manim from the very beginning and provide tutorial and practice examples to streamline learning. To avoid any confusion all examples contain the entire source code.
Basics & Drawing images
First, we focus on how to draw non-animated images. We explore various shapes and how to connect them.
Project setup & compilation
Follow installation instructions ↗ to get Manim on your system. Then setup a project ↗.
This tutorial is created with conjunction with a public Github repository ↗ that you may download and try. In general, you will be able to run a command of the following structure to get an output.
manim [-p] -ql <file.py> <Class>
- Command itself depends on the version you get –
manim
(community version, used here) ormanimgl
(Grant’s version). - Flags you will usually use are
-p
to display the output, and-ql
or-qh
to set quality. They can be squished to e.g.-pql
. - Next,
file.py
points to your source code. For cleanliness, we split examples into different sources and put them into folders, so our command usually contains e.g.examples/shapes.py
. - Last,
Class
refers to a class (that inherits Scene) within the source code. One file can contain many scenes and setting this class selects which one should be prepared. We default its name toMain
but this is just our convention.
If you set up Manim correctly and download the repository you should be able to run the following command that produces and opens the final picture.
manim -pql examples/sample.py Main
import manim
class Main(manim.Scene):
def construct(self):
self.add(manim.Text("Hello Manim!"))
Once you can run Manim and get picture or video proceed with this tutorial.
A note about python
Make sure you are using Python 3 (not Python 2).
To use Manim classes, methods, and constants, we need to include them.
Manim tutorials usually have from manim include *
as the first line.
This includes all Manim things to the main namespace.
At first, this tutorial will include explicitly using from manim include <thing, ...>
or call through Manim (e.g. instead of Scene
and importing it, just import manim
and call manim.Scene
) or its alias (include manim as m
and call m.Scene
).
We will use star inclusion in later examples as we should be familiar with how includes work at that point.
Brief introduction & first examples
A Manim project consists of scenes.
Manim distinguishes two main types of things you have in your code – objects and animations.
When you render a scene that does not include any animation (calling self.animate
or self.wait
) you will get an image, otherwise, the output is video.
As you already saw above, Manim has a class for a scene.
Your python code can live outside of this scene, but whatever you want to be drawn must do something in the scene’s construct(self)
method.
The self here represents the scene and it provides methods that allow you to interact with the scene.
A typical way to add shapes to a scene is via self.add
method.
By default, any object is placed at $(0,0)$ coordinates.
import manim
# <imports>
# other code
class SceneName(manim.Scene):
def construct(self):
# your Manim code
self.add(manim.Text("Hello Manim!"))
There are many things that can be added to a scene.
You may find Manim objects (also called Mobjects) in the documentation ↗.
Many objects “inherit” from others and allow you to add objects using a simpler input method.
For example, Line
draws a line if you provide start and end; TangentLine
is based on Line
and given a specific circle it computes proper endpoints so that the line is tangent to it.
Let us now list majority of the useful geometric Mobjects.
Note that the following (and some of the further) code generates an overview picture. In such cases, the resulting image is more important than the code. It is not necessary to understand the code right now.
from manim import *
config.frame_width=2
class Main(Scene):
def construct(self):
label = MathTex(r'\alpha', color=BLACK)
grp = Group(*[
Dot(),
AnnotationDot(),
LabeledDot(label),
])
self.add(grp.arrange())
from manim import *
config.frame_width=5.5
class Main(MovingCameraScene):
def construct(self):
s = ORIGIN
t = 2*DOWN
self.camera.frame.set(ratio=3)
grp = Group(*[
Line(s, t),
Arrow(s, t),
Arrow(s, t, buff=0),
DoubleArrow(s, t, buff=0),
ArcBetweenPoints(s, t),
CurvedArrow(s, t),
CurvedDoubleArrow(s, t),
CubicBezier(s, s+LEFT/2, t+RIGHT/3, t),
])
self.add(grp.arrange())
from manim import *
config.frame_width=5
def build_arrow(tip):
return Arrow(ORIGIN, 2*DOWN, tip_shape=tip)
class Main(Scene):
def construct(self):
tips = [ArrowTriangleTip, ArrowTriangleFilledTip,
ArrowCircleTip, ArrowCircleFilledTip,
ArrowSquareTip, ArrowSquareFilledTip,
StealthTip]
self.add(Group(*map(build_arrow, tips)).arrange())
from manim import *
config.frame_width = 10
class Main(Scene):
def construct(self):
grp = Group(*[
Square(),
Triangle(),
Circle(),
RegularPolygon(5),
Star(5),
Rectangle(width=3, height=1),
Polygon([0,0,0], [0,1,0], [1,0,0]),
])
self.add(grp.arrange_in_grid(2,4))
from manim import *
config.frame_width=9.5
class Main(Scene):
def construct(self):
grp = Group(*[
Arc(1, 0, PI/2),
ArcBetweenPoints(ORIGIN, DOWN),
AnnularSector(1, 1.2, PI*3/2),
Annulus(1, 1.2),
Circle(1),
Ellipse(1.5, 2),
])
self.add(grp.arrange_in_grid(2,3))
order of adding objects
object methods
- shift
- move_to
- allign_to
other
- to_edge?
group vs vgroup
arrange arrange_in_grid
Configuration
frame size background
Coordinates
[1,2,3]
Manim units (Munits)
8 high, 14.22… wide
configuration?
- frame_width, frame_rate = 60, pixel_height ….background_color, notify_outdated_version
- searches: in the project, OS directory, library’s global config manim cfg write -l cwd
NumberPlane
Animations
add
wait
play
animations:
- add
- change
- mark
- remove