当前位置:   article > 正文

Python视频制作工具Manim入门,文本使用详细介绍

python manim

来源:Python数据之道 (ID:PyDataLab)

作者:阳哥

01写在前面

大家好,我是阳哥。

最近一段时间,我在微信视频号「价值前瞻」和「Python数据之道」发布了一些视频,有不少同学问到这些视频是怎么做的,用什么工具制作的。

在文章 用 python 制作高逼格的数学动画 中,我跟大家介绍了 Manim 这个视频制作工具,以及以及案例演示。

不少同学觉得这个工具不错,问到有没有完整的使用教程或者相关书籍。据我所知,目前应该是没有专门的书籍来介绍这个工具的。至于教程,不同版本的Manim有一部分文档,其中 Manim社区版的文档相对而言要完善些。

我将基于 Manim社区版(Manim Community)给大家分享Manim入门的内容,当前已有的教程包括:

说明:Manim 社区版,经常缩写为 manimce,英文全称是 Manim Community Edition

本次介绍 Manim 中 文本 的使用,使用的版本为 Manim Community v0.14.0,本文内容主要如下:

5d47cc3dbaf74a385addf8340a3762a8.png

02Manim的安装与运行

安装

如何安装社区版Manim,参见下面的官方链接:

https://docs.manim.community/en/stable/installation.html

如何运行 Manim

Manim 绘制图形,首先需要引入 Manim 库,然后将需要绘制的内容封装到一个 类(class) 里面。

社区版的导入代码如下:

from manim import *

对于 编辑好的程序文件( XXXX.py 文件),需要在同一个文件夹下运行命令来运行程序,命令格式如下:

manim -pql XXXX.py DemoSquare

上面的命令行中:

  • manim 是社区版Manim运行程序的主要标志用语;

  • p 表示程序运行后会进行预览(图片或视频);

  • ql 表示低质量(quality low), 其他的选项有 -ql, -qm, -qh, -qk, 分别表示 低质量、正常质量、高质量、4K质量;

  • XXXX.py 是py代码文件;

  • DemoSquare 是 py代码文件中的一个类;

演示过程录屏如下:

96e96fd316a935b8003b2246234a2054.gif

命令行中,还有其他许多参数可以设置,可以通过社区版的支持文档来进一步了解:

https://docs.manim.community/en/stable/tutorials/configuration.html#command-line-arguments

03文本使用介绍

在 Manim社区版中,文本的使用可以分为几个大类,分别是:

  • 纯文本

  • 标记文本

  • LaTex 文本

  • 代码文本

3.1 纯文本

纯文本是最常见的一类文字,在视频中使用的标题、正文等,都可以使用纯文本,在Manim 中,纯文本可以通过 Text() 对象来实现。

比如要输出 文字 “Python数据之道”,核心代码如下:

Text("Python数据之道")

效果如下:

83d14d17f45568c97a106183887ca04a.png
设置文本大小

对于文本而言,设置文本在屏幕中显示的大小,是经常要做的一个事情,Text() 对象可以通过多种方法来实现:

  • 设置 scale 属性值;

  • 设置 set_width 属性值;

  • 设置 font_size 参数值;

  1. # 设置文本大小
  2. class Demo2(Scene):
  3.     def construct(self):
  4.         WaterMark.construct(self)
  5.         s = "Python数据之道"
  6.         t1 = Text(s)
  7.         t1.to_edge(UP,buff=0.5)
  8.         t2 = Text(s).scale(2)
  9.         t2.next_to(t1,DOWN)
  10.         t3 = Text(s).set_width(10)
  11.         t3.next_to(t2,DOWN)
  12.         t4 = Text(s,font_size=40)
  13.         t4.next_to(t3,DOWN)       
  14.         self.add(t1)
  15.         self.play(Write(t2))
  16.         self.play(Create(t3))
  17.         self.play(Write(t4))
  18.         self.wait()

上述代码的实现效果如下:

5b79acbd98cbd615464935189a90a541.png
设置文本颜色

文本颜色设置包括指定某种颜色以及渐变颜色设置,通常情况下,颜色通过 color 参数来设置,渐变颜色通过 gradient 参数来设置。

演示案例的代码如下:

  1. # 设置文本颜色
  2. class Demo3(Scene):
  3.     def construct(self):
  4.         WaterMark.construct(self)
  5.         s = "Python数据之道"
  6.         t1 = Text(s,color=BLUE)
  7.         t1.to_edge(UP,buff=2)
  8.         t2 = Text("一份价值,一份收获",gradient=[BLUE,YELLOW,RED]).next_to(t1,DOWN)
  9.         t3 = Text("Hello World",gradient=[BLUE,YELLOW,RED]).next_to(t2,DOWN)
  10.         t4 = Text("@Python数据之道",gradient=[BLUE,YELLOW,RED],font_size=30,fill_opacity=0.8)
  11.         t4.next_to(t3,DOWN)
  12.         t5 = Text("Python数据之道",gradient=[BLUE,YELLOW,RED]).next_to(t4,DOWN)
  13.         # 当英文和汉字混合时, 当前的manim社区版,使用 gradient 时会出现 bug
  14.         self.add(t1)
  15.         self.play(Write(t2))
  16.         self.play(Create(t3))
  17.         self.play(Write(t4))
  18.         self.play(Write(t5))
  19.         self.wait()

上述代码的实现效果如下:

a267306b0ffed3b7e3bcbf7845ed986b.png

需要注意的是,当英文和汉字混合时, 当前的manim社区版,使用 gradient 时可能会出现 bug,没有渐变的效果,上述案例中的 变量 t5 实例 就没有实现渐变效果。

设置文本样式

文本样式的设置,包括文本加粗、斜体文本、文本字体设置、文本透明度设置、文本换行以及行距设置等。

演示案例的代码如下:

  1. # 设置字体样式
  2. class Demo4(Scene):
  3.     def construct(self):
  4.         WaterMark.construct(self)
  5.         t1 = Text("Python数据之道",font="Alibaba PuHuiTi")
  6.         t1.to_edge(UP,buff=0.5)
  7.         t2 = Text("Python数据之道",color=BLUE,font="Times")
  8.         t2.next_to(t1,DOWN)
  9.         t3 = Text("Python数据之道", weight=BOLD)
  10.         t3.next_to(t2,DOWN)
  11.         t4 = Text("Python数据之道", slant=ITALIC)
  12.         t4.next_to(t3,DOWN)
  13.         t5 = Text("Python数据之道", fill_opacity=0.5)
  14.         t5.next_to(t4,DOWN)
  15.         t6 = Text("Hello\nPython", line_spacing=0.5)
  16.         t6.next_to(t5,DOWN,buff=1).shift(LEFT)
  17.         t7 = Text("Hello\nPython", line_spacing=2)
  18.         t7.next_to(t6,RIGHT,buff=1)
  19.         self.add(t1)
  20.         self.play(Write(t2))
  21.         self.play(Write(t3))
  22.         self.play(Write(t4))
  23.         self.play(Write(t5))
  24.         self.add(t6,t7)
  25.         self.wait()

上述代码的实现效果如下:

5e0425dd38f0475aabcd48c28384cd3d.png

需要主要的是,在选择字体设置时,所选择的字体需要在自己的电脑中已经安装了对应的字体,才会有效果。

此外,在对于非英文字体的设置时,可能有些样式设置会不起作用,具体的需要自己去根据实际情况测试下。

对于咱们而言,一般就是英文和中文的使用,常用的字体加粗、斜体文字、透明度等,是有效的。对于字体,我一般是使用 "Alibaba PuHuiTi" 字体,这个字体可以免费使用。

个性化设置部分文本

在控制显示过程中,经常会遇到只需要显示一段文本中一部分文本的情况,可以通过以下几个参数来进行设置:

  • t2c,全称为 "text2color",用来设置部分文字的颜色;

  • t2f,全称为 “text2font”,用来设置部分文字的字体;

  • t2w,全称为 “text2weight”,用来设置部分文字加粗;

  • t2s,全称为 “text2slant”,用来设置部分文字为斜体;

  • t2g,全称为 “text2gradient”,用来设置部分文字的渐变颜色;

演示案例的代码如下:

  1. # 个性化设置部分文本的样式
  2. class Demo5(Scene):
  3.     def construct(self):
  4.         WaterMark.construct(self)
  5.         t1 = Text("Python数据之道",t2c={"Python":RED,'[7:9]':YELLOW})
  6.         t1.to_edge(UP,buff=0.5)
  7.         t2 = Text("Python数据之道",t2s={"Python":ITALIC})
  8.         t2.next_to(t1,DOWN)
  9.         t3 = Text("Python数据之道", t2w={"Python":BOLD})
  10.         t3.next_to(t2,DOWN)
  11.         t4 = Text("Python数据之道", t2f={"Python":"Times"})
  12.         t4.next_to(t3,DOWN)
  13.         t5 = Text(
  14.             "Hello,PyDataLab"
  15.             t2g={
  16.                 'PyData':[BLUE,YELLOW,RED],
  17.                 # 'offset':"1",
  18.             },
  19.             )
  20.         t5.next_to(t4,DOWN)
  21.         t6 = Text(
  22.             "Hello,Python数据之道"
  23.             t2g={
  24.                 'Python':[BLUE,YELLOW,RED],
  25.             },
  26.             )
  27.         t6.next_to(t5,DOWN)
  28.         t7 = Text(
  29.             "一份价值,一份收获"
  30.             t2g={
  31.                 '一份价值':[BLUE,YELLOW,RED],
  32.             },
  33.             )
  34.         t7.next_to(t6,DOWN)
  35.         # "t2c""t2s""t2w""t2g""t2f" 参数设置,可以直接是 字符串,或者是 字符串的位置切片
  36.         self.add(t1)
  37.         self.play(Write(t2))
  38.         self.play(Write(t3))
  39.         self.play(Write(t4))
  40.         self.play(Write(t5))
  41.         self.play(Write(t6))
  42.         self.play(Write(t7))
  43.         self.wait()

上述代码的实现效果如下:

ece86886f8753cf7107b125b29828060.png

通过上面的代码可以看出,"t2c"、"t2s"、"t2w"、"t2g"、"t2f" 参数设置,可以直接是 字符串,或者是 字符串的位置切片。

需要注意的是,当英文和汉字混合或者全部是中文时, 当前的manim社区版,使用 t2g 对部分文字进行渐变设置 时可能会出现 bug,会出现部分文字渐变效果不完整,或者全部文字都有渐变效果。

纯文本应用案例

下面咱们来看一个用纯文本实现 “Google” 彩色 logo 的案例,如下:

  1. class Demo6(Scene):
  2.     def construct(self):
  3.         WaterMark.construct(self)
  4.         text1 = Text(
  5.             'Google',
  6.             t2c={'[:1]''#3174f0''[1:2]''#e53125',
  7.                  '[2:3]''#fbb003''[3:4]''#3174f0',
  8.                  '[4:5]''#269a43''[5:]''#e53125'}, font_size=58).scale(3)
  9.         self.play(Write(text1),run_time=3)
  10.         self.wait()
  11.         self.play(FadeOut(text1))
  12.         t2 = Text('Google',font_size=120)
  13.         colors = [BLUE, ORANGE, PURPLE, PINK, TEAL,DARK_BROWN, RED,LIGHT_BROWN,GOLD,BLUE_L_C,ORANGE_L_A,PURPLE_E]*10
  14.         # for i in range(len(t2)):
  15.         #     t2[i].set_color(colors[i])
  16.         for letter in t2:
  17.             letter.set_color(np.random.choice(colors,size=1))
  18.         self.play(Write(t2),run_time=3)
  19.         self.wait()

上述代码的实现效果如下:

7a52a90d765f765968725f348d13785f.gif

3.2 标记文本

Manim社区版使用 Pango 来渲染非 LaTex 文本。

Pango标记语言是一种类似 html 的标记语言,可以使用一系列的标记符号。

PangoMarkup is a small markup language like html and it helps you avoid using “range of characters” while coloring or styling a piece a Text. You can use this language with MarkupText.

标记文本的基础应用

一个简单的应用案例如下:

  1. class Markup01(Scene):
  2.     def construct(self):
  3.         WaterMark.construct(self)
  4.         t1 = MarkupText('<span foreground="yellow" size="x-large">Hello, </span> <i>Welcome to </i>ValueLab !"')
  5.         t1.to_edge(UP,buff=2)
  6.         self.add(t1)
  7.         self.wait()
  8.         t2 = MarkupText('<span foreground="yellow" size="x-large">一份价值,</span> 一份 <i>收获</i>!"')
  9.         t2.next_to(t1,DOWN,buff=1)
  10.         self.add(t2)
  11.         self.wait()

上述代码的实现效果如下:

895d788a7f35f01575d043e501d7dd14.png

可以看到,对于 Markup 标记语言,在应用于英文文字的时候,应用效果是挺好的,但对于中文字体,上面的文字中,斜体效果就没有体现出来。不知道是 Pango本身渲染的问题还是 Manim社区版存在一些瑕疵。

当前,Manim中进行文字渲染,支持以下标签:

286ef4adfc246dc1baa2d2e143aa9c4d.png
标记文本的样式设置

标记文本的样式设置包括文字加粗、下划线、斜体、上标、下表、删除线等,演示案例的代码如下:

  1. # 样式设置,加粗、下划线、斜体等
  2. class Markup02(Scene):
  3.     def construct(self):
  4.         WaterMark.construct(self)
  5.         text1 = MarkupText("<b>Hello</b> <i>welcome to</i> <b><i>ValueLab</i></b>")
  6.         text2 = MarkupText("<s>foo</s> <u>bar</u> <big>big</big> <small>small</small>")
  7.         text3 = MarkupText("H<sub>2</sub>O and H<sub>3</sub>O<sup>+</sup>")
  8.         text4 = MarkupText("type <tt>help</tt> for help")
  9.         text5 = MarkupText(
  10.             '<span underline="double">foo</span> <span underline="error">bar</span>'
  11.         )
  12.         group = VGroup(text1, text2, text3, text4, text5).arrange(DOWN)
  13.         self.add(group)

上述代码的实现效果如下:

ae8f53aed0eacc6c4b49a64af648149c.png
标记文本的颜色设置

标记文本的颜色设置,主要是渐变色的设置比较复杂,仔细看下面案例中渐变色设置时的各个参数:

  1. # 颜色设置,设置不同的颜色、渐变色等
  2. class Markup03(Scene):
  3.     def construct(self):
  4.         text1 = MarkupText(
  5.             f'all in red <span fgcolor="{YELLOW}">except this</span>', color=RED
  6.         )
  7.         text2 = MarkupText("nice gradient", gradient=(BLUE, GREEN))
  8.         text3 = MarkupText(
  9.             'nice <gradient from="RED" to="YELLOW">intermediate</gradient> gradient',
  10.             gradient=(BLUE, GREEN),
  11.         )
  12.         text4 = MarkupText(
  13.             'fl ligature <gradient from="RED" to="YELLOW">causing trouble</gradient> here'
  14.         )
  15.         text5 = MarkupText(
  16.             'fl ligature <gradient from="RED" to="YELLOW" offset="1">defeated</gradient> with offset'
  17.         )
  18.         text6 = MarkupText(
  19.             'fl ligature <gradient from="RED" to="YELLOW" offset="1">floating</gradient> inside'
  20.         )
  21.         text7 = MarkupText(
  22.             'fl ligature <gradient from="RED" to="YELLOW" offset="1,1">floating</gradient> inside'
  23.         )
  24.         group = VGroup(text1, text2, text3, text4, text5, text6, text7).arrange(DOWN)
  25.         self.add(group)

上述代码的实现效果如下:

ace63d6b98634a0afad9538e48e9ed5e.png
文字对齐

在书写英文文字时,为了排版效果好看,经常需要将文字进行对齐显示,这个在 Manim中,也可以实现。

演示案例的代码如下:

  1. # 文字对齐
  2. class Markup05(Scene):
  3.     def construct(self):
  4.         WaterMark.construct(self)
  5.         ipsum_text = (
  6.             "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
  7.             "Praesent feugiat metus sit amet iaculis pulvinar. Nulla posuere "
  8.             "quam a ex aliquam, eleifend consectetur tellus viverra. Aliquam "
  9.             "fermentum interdum justo, nec rutrum elit pretium ac. Nam quis "
  10.             "leo pulvinar, dignissim est at, venenatis nisi. Quisque mattis "
  11.             "dolor ut euismod hendrerit. Nullam eu ante sollicitudin, commodo "
  12.             "risus a, vehicula odio. Nam urna tortor, aliquam a nibh eu, commodo "
  13.             "imperdiet arcu. Donec tincidunt commodo enim a tincidunt."
  14.         )
  15.         justified_text = MarkupText(ipsum_text, justify=True).scale(0.4)
  16.         not_justified_text = MarkupText(ipsum_text, justify=False).scale(0.4)
  17.         just_title = Title("Justified")
  18.         njust_title = Title("Not Justified")
  19.         self.add(njust_title, not_justified_text)
  20.         self.play(
  21.             Transform(
  22.                 not_justified_text,
  23.                 justified_text,
  24.             ),
  25.             Transform(
  26.                 njust_title,
  27.                 just_title,
  28.             ),
  29.             run_time=2,
  30.         )
  31.         self.wait(1)

上述代码的实现效果如下:

bf7b50e3cc04e2ce5e043d1df86dd4a5.gif

3.3 LaTex 文本

LaTeX(LATEX,音译“拉泰赫”)是一种基于ΤΕΧ的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在20世纪80年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由TeX所提供的强大功能,能在几天、甚至几小时内生成很多具有书籍质量的印刷品。

对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。这个系统同样适用于生成从简单的信件到完整书籍的所有其他种类的文档。

在 Manim 中使用 latex 文本,需要你的电脑环境中已经安装了 latex的相关软件和支持工具。

在 Manim 中,可以通过以下几种方法来使用 latex 文本,如下:

  • Tex

  • MathTex

  • Title

  • BulletedList

文本型的 LaTex 可以通过 TexTitleBulletedList 来实现,数学公式类型的文本,可以通过 TexMathTex 来实现。

基础应用

先来看一个 latex 的基础应用案例,如下:

  1. class DemoTex01(Scene):
  2.     def construct(self):
  3.         WaterMark.construct(self)
  4.         tex1 = Tex(r"\LaTeX", font_size=144)
  5.         tex1.to_edge(UP,buff=1)
  6.         self.add(tex1)
  7.         self.wait()
  8.         tex2 = Tex(r'$x^2 + y^2 = z^2$', font_size=144)
  9.         tex2.next_to(tex1,DOWN,buff=0.5)
  10.         tex3 = MathTex(r'x^2 + y^2 = z^2', font_size=144,color=BLUE)
  11.         tex3.next_to(tex2,DOWN,buff=0.5)
  12.         self.add(tex2)
  13.         self.wait()
  14.         self.add(tex3)
  15.         self.wait()

上述代码的实现效果如下:

77148d751a1818baa612b4726e9c9e10.png

TexMathTex 中使用字符串时,一般会使用 r"..." 的形式,而不是 '...' 的形式,这是因为在 latex文本中,经常会涉及到一些特殊的字符,比如 \

在进行数学公式的表达时,使用 Tex 时需要在字符串前后添加符号 $,形式为 r"$...$",使用 MathTex 时,形式为 r"..." 就可以了。两者之间的区别,需要注意下。

使用 latex 工具包

在 latex 中输出特殊符号时,可以通过 latex 工具包来实现。

当然,需要你的电脑中已经安装了对应的 latex 工具包。对于没有使用过 latex 的同学来说,这个确实会有些繁琐。

演示案例的代码如下:

  1. # 使用 latex 工具包
  2. class DemoTex02(Scene):
  3.     def construct(self):
  4.         WaterMark.construct(self)
  5.         myTemplate = TexTemplate()
  6.         myTemplate.add_to_preamble(r"\usepackage{mathrsfs}")
  7.         tex = Tex(r'$\mathscr{H} \rightarrow \mathbb{H}$}', tex_template=myTemplate, font_size=144)
  8.         self.add(tex)

上述代码的实现效果如下:

9e78d3a44a0ffc396debc58f91af3a1b.png
数学公式的颜色设置

在 Manim 中,对于数学公式中字符的颜色设置,可以通过参数 set_color_by_texsubstrings_to_isolate 的组合来实现不同的效果。

演示案例的代码如下:

  1. # 数学公式的颜色设置
  2. class DemoTex03(Scene):
  3.     def construct(self):
  4.         WaterMark.construct(self)
  5.         eq1 = MathTex(
  6.             r"e^x = x^0 + x^1 + \frac{1}{2} x^2 + \frac{1}{6} x^3 + \cdots + \frac{1}{n!} x^n + \cdots"
  7.         )
  8.         eq1.scale(1.2)
  9.         eq1.set_color_by_tex("x", YELLOW)
  10.         eq1.to_edge(UP,buff=2)
  11.         self.add(eq1)
  12.         self.wait()
  13.         # self.play(FadeOut(eq1))
  14.         eq2 = MathTex(
  15.             r"e^x = x^0 + x^1 + \frac{1}{2} x^2 + \frac{1}{6} x^3 + \cdots + \frac{1}{n!} x^n + \cdots",
  16.             substrings_to_isolate="x",
  17.         )
  18.         eq2.scale(1.2)
  19.         eq2.set_color_by_tex("x", RED)
  20.         eq2.next_to(eq1,DOWN,buff=1)
  21.         self.add(eq2)
  22.         self.wait()

上述代码的实现效果如下:

4d6d8902439b442887d4a653d294d0bc.png

eq1 中,仅设置参数 set_color_by_tex 时,是对于包含 “x” 的整个公式进行颜色设置;而在 eq2 中,同时设置参数 set_color_by_texsubstrings_to_isolate 时,仅仅对公式中的 “x” 字符进行颜色设置;这两种是不一样的应用场景,大家选择合适的去使用。

我在微信视频号「价值前瞻」中发布的视频 “复利效应” 中就使用到类似的案例。

该视频中涉及数学公式的部分代码如下:

  1. class DemoTex04(Scene):
  2.     def construct(self):
  3.         WaterMark.construct(self)
  4.         equations = VGroup(
  5.             MathTex(
  6.                 r"1.01^{365} = 37.8",
  7.                 # size=80,
  8.             ),
  9.             MathTex(
  10.                 r"1.00^{365} = 1.00",
  11.                 # size=80,
  12.             ),
  13.             MathTex(
  14.                 r"0.99^{365} = 0.03",
  15.                 # size=80,
  16.             ),
  17.         )
  18.         # 设置宽度
  19.         # equations.set_width(FRAME_WIDTH-4)
  20.         equations.set_width(8)
  21.         for equation in equations:
  22.             equation.set_color_by_tex_to_color_map({
  23.                 "1.01": BLUE,
  24.                 "0.99": RED,
  25.             })
  26.         equations.arrange(DOWN, buff=0.7, aligned_edge=LEFT)
  27.         self.play(Write(equations[0]))
  28.         self.wait()
  29.         self.play(Write(equations[2]))
  30.         self.wait()
  31.         self.play(Write(equations[1]))
  32.         self.wait()
  33.         self.play(equations[1].animate.set_opacity(0.2))
  34.         self.wait()

上述代码的实现效果如下:

bf838e97aa4efe6dd32ab34569f8072f.png
tex 模板应用

在 LaTex 中,可以通过设置使用的模板,来设置使用的字体。此外,在使用中文字符时,经常需要设置中文的模板(一般使用 ctex)。

演示案例的代码如下:

  1. # tex 模板应用
  2. class DemoTex05(Scene):
  3.     def construct(self):
  4.         WaterMark.construct(self)
  5.         tex1 = Tex(r'$x^2 + y^2 = z^2$', tex_template=TexFontTemplates.french_cursive, font_size=144)
  6.         tex1.to_edge(UP,buff=1)
  7.         self.add(tex1)
  8.         self.wait()
  9.         tex2 = Tex(r'Hello 你好 \LaTeX', tex_template=TexTemplateLibrary.ctex, font_size=144)
  10.         tex2.next_to(tex1,DOWN,buff=0.5)
  11.         self.add(tex2)
  12.         self.wait()

上述代码的实现效果如下:

cc19db962403822588a2f8c2a2ee1b79.png

对于 TexFontTemplates,可以使用的模板说明如下:

A collection of TeX templates for the fonts described at http://jf.burnol.free.fr/showcase.html

公式换行

在数学公式中,可以实现换行效果,如下:

  1. # 公式换行
  2. class DemoTex06(Scene):
  3.     def construct(self):
  4.         WaterMark.construct(self)
  5.         tex1 = MathTex(
  6.             r'f(x) &= 3 + 2 + 1\\ &= 5 + 1 \\ &= 6'
  7.             font_size=96,
  8.         )
  9.         self.add(tex1)
  10.         self.wait()
  11.         self.play(FadeOut(tex1))
  12.         tex2 = MathTex(
  13.             r'f(x) &= 3 + 2 + 1\\ &= 5 + 1 \\ &= 6'
  14.             font_size=96,
  15.             substrings_to_isolate=['5','3'],
  16.         )
  17.         tex2.set_color_by_tex_to_color_map({
  18.                 "5": BLUE,
  19.                 "3": RED,
  20.             })
  21.         self.add(tex2)
  22.         self.wait()

上述代码的实现效果如下:

4263d6b74235f2ed28c296148020d07e.gif
Title 对象应用

在视频中设置文字标题时,可以直接使用 Title 对象,需要说明的是,Title 对象是基于 Tex 来实现的,在涉及中文输出时,需要设置使用的模板为中文适用的模板。

演示案例的代码如下:

  1. # Title 对象应用
  2. class DemoTex07(Scene):
  3.     def construct(self):
  4.         WaterMark.construct(self)
  5.         title1 = Title("Hello,title")
  6.         self.add(title1)
  7.         self.wait()
  8.         self.play(FadeOut(title1))
  9.         # 使用 “Title” 对象,当有中文时,需要设置中文字体模板(电脑中需要安装了 ctex)
  10.         title2 = Title("你好,title",tex_template=TexTemplateLibrary.ctex)
  11.         self.add(title2)
  12.         self.wait()

上述代码的实现效果如下:

c0176b332084295d690324027b8f573a.gif
列表类型的文本

在文本的使用过程中,会时不时涉及到 列表型文本,目前,在 Manim 中,可以直接实现无序号型的列表文本,通过 BulletedList 对象来实现。

演示案例的代码如下:

  1. # 列表类型的文本
  2. class DemoTex08(Scene):
  3.     def construct(self):
  4.         blist = BulletedList("Python""Java""C++", height=2, width=2)
  5.         blist.set_color_by_tex("Python", RED)
  6.         blist.set_color_by_tex("Java", GREEN)
  7.         blist.set_color_by_tex("C++", BLUE)
  8.         self.add(blist)

上述代码的实现效果如下:

21a858dbb1b4dbbf6450b64450c58128.png

3.4 代码文本

在 IT编程领域,代码的高亮显示是一个常见的需求,在 Manim 制作的视频中,也可以实现代码高亮的效果,主要是通过 Code() 对象来实现。

下面以快速排序的Python代码为例,来演示如何在视频中进行代码高亮显示。

  1. class Code1(Scene):
  2.     def construct(self):
  3.         WaterMark.construct(self)
  4.         code_str_1 = """
  5.         def quickSort(Array):  
  6.             n = len(Array)
  7.             if n <= 1:
  8.                 return Array
  9.             baseline = Array[0]
  10.             left = [Array[i] for i in range(1, len(Array)) if Array[i] < baseline] 
  11.             right = [Array[i] for i in range(1, len(Array)) if Array[i] >= baseline]
  12.             return quickSort(left) + [baseline] + quickSort(right)
  13.         """
  14.         code1 = Code(
  15.             code=code_str_1,
  16.             tab_width=4,
  17.             background="window",
  18.             language="Python",
  19.             font="Monospace",
  20.             insert_line_no=False,  # 是否显示代码行数
  21.             style='monokai',
  22.         )
  23.         code1.scale(0.8).to_edge(UP,buff=1)
  24.         self.play(Write(code1))
  25.         self.wait()

代码高亮效果如下:

92ba6f5f149080d1ebebd2c198903291.png

上述代码中,变量 code_str_1 是快速排序算法的Python实现代码, 变量 code1Code() 对象的实例, Code() 有许多参数可以进行设置,这里只对部分参数进行设置:

  • background 参数,可以选择 “rectangle” 或 “window”,默认是 “rectangle”,我自己一般喜欢用 “window”;

  • language 参数是所用的编程语言,支持常用的编程语言;

  • font 参数,代码字体,默认为  "Monospac821 BT",我一般用 “Monospace”;

  • insert_line_no 参数,是否显示代码行数,默认是 True;需要注意的是,在显示代码行数时,有时行数与代码的对齐效果不一定完美;

  • style 参数,代码显示风格,有多种风格可以选择,其可选代码样式来源于 “pygments” (https://pygments.org/docs/styles/)。可在Python中运行代码来获取支持的样式。

    1. from pygments.styles import get_all_styles
    2. styles = list(get_all_styles())
    3. style支持的样式如下:

    ['default', 'emacs', 'friendly', 'colorful', 'autumn', 'murphy', 'manni', 'monokai', 'perldoc', 'pastie', 'borland', 'trac', 'native', 'fruity', 'bw', 'vim', 'vs', 'tango', 'rrt', 'xcode', 'igor', 'paraiso-light', 'paraiso-dark', 'lovelace', 'algol', 'algol_nu', 'arduino', 'rainbow_dash', 'abap', 'solarized-dark', 'solarized-light', 'sas', 'stata', 'stata-light', 'stata-dark', 'inkpot'] 默认的样式为 'vim',我一般喜欢用 'monokai' 样式。1189f941eaec2d01c277f9e3202b2001.png

再选择一款浅色的样式('solarized-light'),并设置不同的参数值,来对比下效果,如下:

  1. class Code1(Scene):
  2.     def construct(self):
  3.         WaterMark.construct(self)
  4.         code_str_1 = """
  5.         def quickSort(Array):  
  6.             n = len(Array)
  7.             if n <= 1:
  8.                 return Array
  9.             baseline = Array[0]
  10.             left = [Array[i] for i in range(1, len(Array)) if Array[i] < baseline] 
  11.             right = [Array[i] for i in range(1, len(Array)) if Array[i] >= baseline]
  12.             return quickSort(left) + [baseline] + quickSort(right)
  13.         """
  14.         code1 = Code(
  15.             code=code_str_1,
  16.             tab_width=4,
  17.             background="window",
  18.             language="Python",
  19.             font="Monospace",
  20.             insert_line_no=False,  # 是否显示代码行数
  21.             style='monokai',
  22.         )
  23.         code1.scale(0.8).to_edge(UP,buff=1)
  24.         self.play(Write(code1))
  25.         self.wait()
  26.         code2 = Code(
  27.             code=code_str_1,
  28.             tab_width=4,
  29.             background="rectangle", # rectangle , window
  30.             language="Python",
  31.             font="Monospace",
  32.             insert_line_no=True,  # 是否显示代码行数
  33.             style='solarized-light',
  34.             # line_spacing=0.3,
  35.         )
  36.         code2.scale(0.8)
  37.         code2.next_to(code1,DOWN,buff=0.5)
  38.         self.play(Write(code2))
  39.         self.wait()

代码高亮效果如下:

d0d6c8737a43924b888f90f788b3a287.png

Code() 对象还有更多的参数可以进行设置,详细的参数设置说明,大家可以通过官方文档来了解。

af6b368fa638600ed7f826ee2fe3c089.png

官方文档地址:

https://docs.manim.community/en/stable/reference/manim.mobject.svg.code_mobject.Code.html#manim.mobject.svg.code_mobject.Code

04小结

文本的使用,是咱们最常见的领域,在使用文本时,从频率来看,纯文本 是用的最多的,标记文本是对纯文本的进一步拓展,而 latex 文本,则是 针对数学公式等特殊且频率较高的场景来使用的,至于 代码高亮,则是在IT编程特定领域进行应用。

对于涉及中文的使用,经常需要通过 latex 来实现一些效果,因此,对想进一步深入了解中文排版的同学来,可能需要有一些 latex 的基础知识。

熟练的使用文本,可以给视频的排版和外观带来不少好处,不要小看这些哦。

本文中所使用的源代码,大家可以在公众号「Python数据之道」回复 manim 来获取。

相关阅读:


大家读完顺手点下右下角的  “在看” ,就是最大的鼓励和支持了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/325934
推荐阅读
相关标签
  

闽ICP备14008679号