前两篇介绍了基本几何图形外形、位置及动作的定义。
3Blue1Brown 动画制作教程(1)zhuanlan.zhihu.com 3Blue1Brown 动画制作教程(2)zhuanlan.zhihu.com本文主要涉及与图形相辅相成的文字的外形、位置及动作的定义。
美观、灵动的文字亦是 3B1B 动画的一大亮点,文字对象通常由一个称为 TextMobject (Text Math object) 的类实例化得到,TextMobject 类继承于前面图形所属的 VMobject (Vectorized Math object) 类,强调这一点的原因是:由这种继承关系可知前两篇适用于图形对象的那些方法同样也适用于文字对象。
现在打开 manim 根目录下的 manim_tutorial_P37.py 教程文件,找到其中名为 AddingText 的类:
1. class AddingText(Scene):
2. #Adding text on the screen
3. def construct(self):
4. my_first_text=TextMobject("Writing with manim is fun")
5. second_line=TextMobject("and easy to do!")
6. second_line.next_to(my_first_text,DOWN)
7. third_line=TextMobject("for me and you!")
8. third_line.next_to(my_first_text,DOWN)
9.
10. self.add(my_first_text, second_line)
11. self.wait(2)
12. self.play(Transform(second_line,third_line))
13. self.wait(2)
14. second_line.shift(3*DOWN)
15. self.play(ApplyMethod(my_first_text.shift,3*UP))
为了实现这段由文字组成的对话,可以用之前的指令格式,以管理员模式打开 Anaconda Prompt ,跳转到 manim 的根目录,由于动画分辨率低文字可能显示不佳,所以可以把最后一个参数改为“-p”:
python -m manim manim_tutorial_P37.py AddingText -p
或者用一种简化命令:
python -m manim manim_tutorial_P37.py -pl
该命令只有前四个参数及最后一个输出调整参数,输入回车后会显示脚本中所有的类,只需要输入对应的编号就能实例化对应的类,这里输入数字 2 后回车即可。
注释:如果生成文字的过程当中出现 .svg 文件无法生成的情况,以管理员模式分别运行一下几条命令之后再运行上述命令(如果没有出现错误则不必了):
现在分析一下代码内容,前3行就不多说了,前两篇已经说得很清楚了,直接看第4行到第8行:
4. my_first_text=TextMobject("Writing with manim is fun")
5. second_line=TextMobject("and easy to do!")
6. second_line.next_to(my_first_text,DOWN)
7. third_line=TextMobject("for me and you!")
8. third_line.next_to(my_first_text,DOWN)
4、5、8行分别通过实例化 TextMobject 类得到三条文字,如果不加其他设定,文字在显示的时候默认是置于画面中心的,为了使得文字按需放置,第6行和第8行应用 next_to() 方法将第二条文字与第三条文字均置于第一条文字的正下方,之间的距离都是1个单位,因为 参数 “DOWN” 对应的是(0,-1,0)向量,在教程(2)中已经说过。这样文字对象的内容及其初始位置都定义好了,接下来就是定义如何去显示这些文字。
10. self.add(my_first_text, second_line)
11. self.wait(2)
12. self.play(Transform(second_line,third_line))
13. self.wait(2)
14. second_line.shift(3*DOWN)
15. self.play(ApplyMethod(my_first_text.shift,3*UP))
为了方便查看效果,在这里再放一次动画:
细心的朋友一定会发现这里面需要注意好几个点:
首先文字的添加与动作命令与前面定义图形时的方法是完全一致的,妙啊;
然后,第12行虽然将第二条文字的切换为了第三条文字,但是第14行移动的依然是对 second_line 进行操作,也就是说,Transform() 方法是在将其中输入的第二个参数所指代对象的所有属性赋予给了第一个参数所指代对象,但并没有改变第一个参数所指代对象的名称;
最后,直接使用 shift() 方法和借用 ApplyMethod() 间接实现 shift() 方法的本质不同在于,shift() 是直接实现图形或文字对象在两个坐标之间的跳转,而 ApplyMethod() 则可以实现在两个位置之间切换时的补帧动画,格式是 ApplyMethod(对象名.定位方法名, 定位向量) ,注意在 ApplyMethod() 中输入参数的时候,定位方法名后面是没有小括号的。
接着,介绍更多关于文字的操作,找到 manim_tutorial_P37.py 脚本文件中名为 AddingMoreText 的类:
1. class AddingMoreText(Scene):
2. #Playing around with text properties
3. def construct(self):
4. quote = TextMobject("Imagination is more important than knowledge")
5. quote.set_color(RED)
6. quote.to_edge(UP)
7. quote2 = TextMobject("A person who never made a mistake never tried anything new")
8. quote2.set_color(YELLOW)
9. author=TextMobject("-Albert Einstein")
10. author.scale(0.75)
11. author.next_to(quote.get_corner(DOWN+RIGHT),DOWN)
12.
13. self.add(quote)
14. self.add(author)
15. self.wait(2)
16. self.play(Transform(quote,quote2),ApplyMethod(author.move_to,quote2.get_corner(DOWN+RIGHT)+DOWN+2*LEFT))
17. self.play(ApplyMethod(author.scale,1.5))
18. author.match_color(quote2)
19. self.play(FadeOut(quote))
这里主要的新内容有:
以管理员模式打开 Anaconda Prompt ,跳转到 manim 的根目录,输入:
python -m manim manim_tutorial_P37.py AddingMoreText -p
对于其中的展示部分的解释:
13. self.add(quote)
14. self.add(author)
15. self.wait(2)
16. self.play(Transform(quote,quote2),ApplyMethod(author.move_to,quote2.get_corner(DOWN+RIGHT)+DOWN+2*LEFT))
17. self.play(ApplyMethod(author.scale,1.5))
18. author.match_color(quote2)
19. self.play(FadeOut(quote))
除此之外,还可以定义文字的旋转和高亮显示。找到 manim_tutorial_P37.py 脚本文件中名为 RotateAndHighlight 的类:
1. class RotateAndHighlight(Scene):
2. #Rotation of text and highlighting with surrounding geometries
3. def construct(self):
4. square=Square(side_length=5,fill_color=YELLOW, fill_opacity=1)
5. label=TextMobject("Text at an angle")
6. label.bg=BackgroundRectangle(label,fill_opacity=1)
7. label_group=VGroup(label.bg,label) #Order matters
8. label_group.rotate(TAU/8)
9. label2=TextMobject("Boxed text",color=BLACK)
10. label2.bg=SurroundingRectangle(label2,color=BLUE,fill_color=RED, fill_opacity=.5)
11. label2_group=VGroup(label2,label2.bg)
12. label2_group.next_to(label_group,DOWN)
13. label3=TextMobject("Rainbow")
14. label3.scale(2)
15. label3.set_color_by_gradient(RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE)
16. label3.to_edge(DOWN)
17.
18. self.add(square)
19. self.play(FadeIn(label_group))
20. self.play(FadeIn(label2_group))
21. self.play(FadeIn(label3))
新内容主要在文字对象的定义部分:
这里关键在于组合的概念及层的概念,由于图形文字之间有重叠部分,要记住的是,先展现出来的图形、文字在下层,后展现的图形、文字在上层。
另外,用BackgroundRectangle() 定义出来的矩形默认是不显示边框的,而SurroundingRectangle() 定义出来的则是矩形框。
以管理员模式打开 Anaconda Prompt ,跳转到 manim 的根目录,输入:
python -m manim manim_tutorial_P37.py RotateAndHighlight -p
——
有知友 @Raion 问能不能渲染中文,是可以的,而且方法很简单,只需要将~manimmanimlibconstants.py 文件中的 TEX_USE_CTEX = False 改为 TEX_USE_CTEX = True 即可,甚至也适用于日文:
class Chinese(Scene):
def construct(self):
line1=TextMobject("你好")
line2=TextMobject("こんにちは")
line2.shift(DOWN)
self.play(Write(line1))
self.play(Write(line2))
self.wait(2)
将上面的代码添加到教程代码 manim_tutorial_P37.py 中然后以管理员模式启用 Anaconda prompt ,跳转到 manim 的根目录,输入:
python -m manim manim_tutorial_P37.py Chinese -p
由于 LaTeX 的安装配置的一些不明原因,可能会导致有的用户字体包不完备,运行时出错,一时间也找不到问题究竟出在哪,也可以试试以下代码,算是权宜之计。不过我个人还是不太建议在学习如何使用 manim 的时候尝试中文或其他语言,因为编译的时候可能出现各种各样的问题,不妨先只用英文,学会最基本的编程方法,之后有余力再去解决中文带来的各种 Bug:
class Chinese(Scene):
def construct(self):
line1=Text("你好",font='songti')
line2=Text("こんにちは",font='mincho')
line2.shift(DOWN)
self.play(Write(line1))
self.play(Write(line2))
self.wait(2)
看完前三篇教程,相信大家对图形及文字的定义和展现方法已经有了系统的认识,manim 对图形的处理手段和对文字的处理手段是类似的,只是文字相对图形尤其自身的一些特性,毕竟文字类 TextMobject 是矢量化类 VMobject 的一个子类。更多的图形、文字相关的内容还需要自己动手编程来实训。下一篇将重点说说数学公式。
李狗嗨:3Blue1Brown 动画制作教程(4)zhuanlan.zhihu.com更多内容,尽在专栏:
直观の数学zhuanlan.zhihu.com