Manim中渲染中文字体和数学公式报错

这两天才发现的一个问题,就是我安装的Manim在渲染代码的时候,如果出现中文和公式并存的情况下,会不停地报错,当然这个问题也不是绝对的,如果是单纯的中文问题,使用Text一般情况下也没有问题,单纯的使用Mathtext调用公式,也没有问题,就是中文字体和公式同时出现的时候报错。

我这里显示的是

1
ValueError: Latex error converting to dvi

然后是让你查看日志文件,其实这个问题前两天就出现过,相同的代码,放在我的Manim环境中就不能渲染,朋友的电脑就可以渲染。互联网的方法也试过但是效果不明显,直到有个朋友的一篇文章提醒了,就是配置的LaTeX有问题,导致渲染数学公式或者中文字体报错了。修改方法也很简单,找到Python安装文件夹

1
yourpath\Python\Lib\site-packages\manim\utils

然后按照上面的路径一直查找,找到utils文件夹里面的

1
tex.py

1
tex_templates.py

两个文件,打开tex.py文件之后,在大约21行的位置,找到

1
_DEFAULT_PREAMBLE = r"""\usepackage[english]{babel}

然后再后面添加

1
\usepackage{CTEX}

添加完之后是这个样子

打开tex_templates.py文件之后,在大约15行的位置,找到

1
def _new_ams_template() -> TexTemplate:

然后在后面添加

1
\usepackage{CTEX}

添加完成之后是这个样子

两份文件添加好代码之后记得保存,然后用下面的代码进行渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
from manim import *
import numpy as np

class CircleTangent(Scene):
def construct(self):
# 第一部分:封面
title = Text("圆的切线:几何关系与推导", font_size=48, color=BLUE)
subtitle = Text("几何直观与数学推导", font_size=36, color=GREEN)
subtitle.next_to(title, DOWN, buff=0.5)

self.play(Write(title), Write(subtitle))
self.wait(2)
self.play(FadeOut(title), FadeOut(subtitle))

# 第二部分:几何演示
# 创建坐标系
axes = Axes(
x_range=[-4, 4, 1],
y_range=[-3, 3, 1],
x_length=8,
y_length=6,
axis_config={"color": WHITE, "stroke_width": 2},
)
axes.add_coordinates()

# 创建圆:圆心(0,0),半径2
circle = Circle(radius=2, color=YELLOW, stroke_width=4)
circle.move_to(ORIGIN)

# 圆心标记
center = Dot(ORIGIN, color=RED, radius=0.08)
center_label = MathTex("O", color=RED).next_to(ORIGIN, DL, buff=0.1)

# 圆上一点P
p_angle = PI / 3# 60度
p_point = circle.point_at_angle(p_angle)
p_dot = Dot(p_point, color=GREEN, radius=0.08)
p_label = MathTex("P", color=GREEN).next_to(p_point, UR, buff=0.1)

# 显示坐标系和圆
self.play(Create(axes), run_time=1.5)
self.play(Create(circle), run_time=2)
self.play(FadeIn(center), Write(center_label))
self.play(FadeIn(p_dot), Write(p_label))
self.wait(1)

# 绘制半径OP
radius = Line(ORIGIN, p_point, color=RED, stroke_width=4)
radius_label = MathTex("\\text{半径 } OP", color=RED).next_to(radius.get_center(), LEFT, buff=0.2)

self.play(Create(radius), Write(radius_label))
self.wait(1)

# 绘制切线(垂直于半径)
radius_vector = p_point - ORIGIN
tangent_vector = np.array([-radius_vector[1], radius_vector[0], 0]) # 旋转90度
tangent_vector = tangent_vector / np.linalg.norm(tangent_vector) # 单位化

# 绘制切线(长度为4)
tangent_line = Line(
p_point - 2 * tangent_vector,
p_point + 2 * tangent_vector,
color=BLUE,
stroke_width=4
)
tangent_label = MathTex("\\text{切线}", color=BLUE).next_to(tangent_line.get_center(), UP, buff=0.2)

self.play(Create(tangent_line), Write(tangent_label))
self.wait(1)

# 显示垂直符号
right_angle = RightAngle(radius, tangent_line, length=0.3, color=GREEN, stroke_width=4,quadrant=(-1, 1))
self.play(Create(right_angle))

# 垂直关系文本
perpendicular_text = MathTex("OP \\perp \\text{切线}", color=GREEN, font_size=36)
perpendicular_text.next_to(right_angle,RIGHT,buff=0.5)

self.play(Write(perpendicular_text))
self.wait(2)

# 第三部分:缩小几何图形并移至左上角,同时显示数学推导
# 创建几何图形组
geometry_group = VGroup(axes, circle, center, center_label, p_dot, p_label,
radius, radius_label, tangent_line, tangent_label,
right_angle, perpendicular_text)

# 缩小并移动几何图形到左上角
self.play(
geometry_group.animate.scale(0.6).to_corner(LEFT, buff=0.5),
run_time=2
)

# 显示数学推导标题
derivation_title = Text("数学推导", font_size=36, color=ORANGE)
derivation_title.to_edge(UP).shift(DOWN * 0.5)
self.play(Write(derivation_title))

# 推导步骤
steps = VGroup(
MathTex("\\text{1. 已知:圆方程 } (x-a)^2 + (y-b)^2 = r^2"),
MathTex("\\text{2. 圆心 } O(a,b), \\text{ 切点 } P(x_0, y_0)"),
MathTex("\\text{3. 半径斜率: } k_{OP} = \\frac{y_0 - b}{x_0 - a}"),
MathTex("\\text{4. 切线斜率: } k = -\\frac{1}{k_{OP}} = -\\frac{x_0 - a}{y_0 - b}"),
MathTex("\\text{5. 切线方程: } y - y_0 = k(x - x_0)"),
MathTex("\\text{6. 代入得: } y - y_0 = -\\frac{x_0 - a}{y_0 - b}(x - x_0)"),
MathTex("\\text{7. 整理: } (x_0 - a)(x - a) + (y_0 - b)(y - b) = r^2")
)

steps.arrange(DOWN, aligned_edge=LEFT, buff=0.3)
steps.scale(0.7)
steps.next_to(derivation_title, DOWN, buff=0.5).to_edge(RIGHT, buff=1)

# 逐步显示推导过程
for step in steps:
self.play(Write(step), run_time=1.5)
self.wait(0.5)

self.wait(2)

# 第四部分:具体实例 - 清除前面的所有内容
self.play(
FadeOut(geometry_group),
FadeOut(derivation_title),
FadeOut(steps)
)原作者的代码还要长一些,我做了适当的修改,主要是用来做圆的切斜的一些知识,渲染的过程中,会出现一些**LaTeX**文件包的提示,和我们第一次安装完Manim之后进行代码测试的时候一样,例如提示安装**CTEX.sty**文件,从提示来看是ctex宏包的一部分,点击安装就可以

接下来还会安装CJKutf8.sty文件,从提示来看是cjk宏包的一部分

接下来还会安装CJKpunct.sty文件,从提示来看是cjkpunct宏包的一部分

接下来还会安装zhnumber.sty文件,从提示来看是zhnumber宏包的一部分

接下来还会安装UGBK.sfd文件,从提示来看是ttf2pk宏包的一部分

接下来还会安装unisong53.tfm文件,从提示来看是zhmetrics宏包的一部分

上面安装的LaTeX文件包我也不知道什么意思,按照尝试错误的想法,进行安装,估计朋友的安装包可多可少,但是可以通过上面的测试代码进行测试,如果能够渲染成功,基本上就不会再出现类似的公式中包裹中文出错的问题,下面是渲染的结果

至此大功告成,需要注意的是 如果文本中只有汉字,则使用Text方法 如果是在数学公式中有汉字,则使用MathTex方法 下面,常用的格式

1
MathTex("\\text{文字} 数学公式")

好了,今天的知识总结就到这里,希望能够帮助到有同样困惑的朋友。