为什么要文字对齐 ?
对齐原则在现实生活中无处不在,比如:书籍、货架、地铁座位等等;对齐的目的其实就是在规整文案信息,对齐有利于信息传达以及视觉规范,当我们做文字编排工作时,要根据构图形式选择合理的对齐原则,每种对齐形式所传达的视觉感受也不同:左对齐、右对齐给人以整齐、严谨、划分明显的感受;居中对齐则属于更加活跃、可塑性强;而两端对齐更适用于文本段落,底部对齐以及顶部对齐在做海报时的装饰性文本会用到。
用manim实现字体的对齐
接下来我们一步一的来,实现文字对齐
第一步:无法对齐,都指向目标的中间点
from manim import * # 导入manim库,允许我们创建数学动画
class LinearAlgebraDiagram(Scene): # 定义一个名为LinearAlgebraDiagram的场景类
def construct(self): # 定义构造函数,创建场景中的元素
# 创建中心文本
title = Text("Linear Algebra", font_size=48).set_color(WHITE) # 创建主标题文本,字体大小为48,颜色为白色
subtitle = Text("线性代数", font_size=36).next_to(title, DOWN) # 创建副标题文本,字体大小为36,并将其放置在主标题下方
Vt = VGroup(title, subtitle).arrange(DOWN, buff=0.5).shift(LEFT * 3) # 将标题和副标题组合成一个组,垂直排列,距离为0.5,向左移动3个单位
# 创建学科文本
subjects = [ # 创建一个包含不同学科的列表
Text("Computer science", font_size=36).shift(LEFT * 3 + DOWN * 2), # 计算机科学
Text("Physics", font_size=36).shift(LEFT * 3 + DOWN * 3), # 物理
Text("Electrical engineering", font_size=36).shift(LEFT * 3 + DOWN * 4), # 电气工程
Text("Mechanical engineering", font_size=36).shift(LEFT * 3 + DOWN * 5), # 机械工程
Text("Statistics", font_size=36).shift(LEFT * 3 + DOWN * 6), # 统计学
]
subject_group = VGroup(*subjects).arrange(DOWN, buff=0.5).shift(RIGHT * 3) # 将所有学科文本组合成一个组,垂直排列,右移3个单位
# 创建箭头
arrows = [] # 初始化一个空列表以存储箭头
for subject in subjects: # 对于每个学科文本
arrow = Arrow(start=title.get_bottom(), end=subject.get_top(), buff=0.1, color=YELLOW) # 创建箭头,起点为主标题底部,终点为学科文本顶部,颜色为黄色
arrows.append(arrow) # 将箭头添加到列表中
# 添加元素到场景中
self.play(Write(title), Write(subtitle)) # 播放动画,将主标题和副标题写入场景中
self.wait(1) # 等待1秒
for arrow, subject in zip(arrows, subjects): # 逐个播放箭头和学科文本的动画
self.play(Create(arrow), Write(subject)) # 创建箭头和写入学科文本
self.wait(0.5) # 每次动画之间等待0.5秒
self.wait(2) # 最后等待2秒
运行结果:
代码解释:
-
引入库: 最开始,代码导入
manim
库,这是一个用于创建数学和科学可视化动画的Python库。 -
创建场景类:
LinearAlgebraDiagram
继承自Scene
类。该类包含一个construct
方法,用于定义场景中的所有元素。 -
添加文本元素: 使用
Text
创建主标题和副标题,并通过VGroup
将它们组合在一起。 -
创建学科列表: 列表
subjects
包含多个学科的文本对象,每个对象都有其自身的位置。 -
箭头制作: 使用循环为每一个学科创建箭头,从主标题到底部学科文本,并将箭头存储在列表中。
-
动画播放: 使用
self.play
和self.wait
方法添加动态效果,使标题、副标题、学科文本和箭头逐渐出现在动画中。
此代码的最终效果是在一个场景中演示线性代数及其相关学科,使用加载动画显示文本和箭头。
第二步:对文字
from manim import * # 导入manim库,允许我们进行数学动画的创建
class AlignTextExample(Scene): # 定义一个名为AlignTextExample的场景类,继承自Scene
def construct(self): # 定义构造函数,创建场景中的元素
# 创建两个文本
title = Text("Linear Algebra", font_size=48).set_color(WHITE) # 创建主标题文本,字体大小为48,颜色为白色
subtitle = Text("线性代数", font_size=48) # 创建副标题文本,字体大小为48
# 将副标题移动到主标题的下方,并且左边对齐
subtitle.next_to(title, DOWN, buff=0) # 将副标题紧挨在主标题下方,垂直对齐
# 获取标题和副标题的宽度
title_width = title.width # 获取主标题的宽度
subtitle_width = subtitle.width # 获取副标题的宽度
# 计算最大宽度,并根据最大宽度调整文本位置
max_width = max(title_width, subtitle_width) # 计算两个文本中最大的宽度
# 将两个文本居左对齐
title.shift(LEFT * (max_width - title_width) / 2) # 将主标题左移,使其与副标题左边对齐
subtitle.shift(LEFT * (max_width - subtitle_width) / 2) # 将副标题左移,使其与主标题左边对齐
# 使用VGroup将它们组合
texts = VGroup(title, subtitle) # 将主标题和副标题组合成一个组
# 将整个组合居中显示
texts.move_to(ORIGIN) # 将组合的中心移动到原点(屏幕中心)
# 将组合添加到场景中
self.add(texts) # 将准备好的文本组合添加到场景中
运行结果:
注释解释:
-
from manim import *
: 这行引入manim
库的所有功能,帮助我们生成动画。 -
class AlignTextExample(Scene):
: 定义了一个新的场景类AlignTextExample
,它将展示对齐文本的示例。 -
def construct(self):
:construct
方法是定义场景中要展示的内容的地方。 -
创建文本: 使用
Text
类创建了主标题(“Linear Algebra”)和副标题(“线性代数”)的文本对象。 -
文本对齐: 将副标题放置在主标题的正下方,接着获取两个文本的宽度,以便后面进行对齐。
-
宽度计算: 计算出两段文本的最大宽度,在之后的步骤中用来进行对齐。
-
位置调整: 根据最大宽度将主标题和副标题的位置调整,使其左边对齐。
-
组合文本: 使用
VGroup
将主标题和副标题组合在一起,便于统一操作。 -
居中显示: 将组合文本的中心移动到屏幕的中心(原点)。
-
添加到场景: 将组合后的文本添加到场景中以显示。
代码整体解释:
该代码的目的是创建一个包含主标题和副标题的简单场景,并使其左对齐。通过使用宽度计算和位移操作,确保两个文本的左边缘对齐,然后将整个文本组合居中放置在画布上。这种对齐方式在制作动画时很有用,可以确保文本显示的整洁美观。最终,所有内容被添加到场景中,以便在动画播放时展示出来。
manim中self目标的对齐
第一步,创建主标题和副标题
from manim import *
class LinearAlgebraDiagram12(Scene):
def construct(self):
# 创建中心文本
title = Text("Linear Algebra", font_size=48).set_color(WHITE)
subtitle = Text("线性代数", font_size=48)
# 将副标题移动到主标题的下方,并且左边对齐
subtitle.next_to(title, DOWN, buff=0) # 把副标题紧挨在主标题下方
# 获取标题和副标题的宽度
title_width = title.width
subtitle_width = subtitle.width
# 计算最大宽度,并根据最大宽度调整文本位置
max_width = max(title_width, subtitle_width)
# 将两个文本居左对齐
title.shift(RIGHT * (max_width - title_width) / 2)
subtitle.shift(RIGHT * (max_width - subtitle_width) / 2)
# 使用VGroup将它们组合
texts = VGroup(title, subtitle).shift(3*LEFT)
# 将整个组合居中显示
# 将组合添加到场景中
#self.add(texts)
self.play(Write(texts))
# 创建学科文本
subjects = [
Text("Computer science", font_size=36).shift(LEFT * 3 + DOWN * 2),
Text("Physics", font_size=36).shift(LEFT * 3 + DOWN * 3),
Text("Electrical engineering", font_size=36).shift(LEFT * 3 + DOWN * 4),
Text("Mechanical engineering", font_size=36).shift(LEFT * 3 + DOWN * 5),
Text("Statistics", font_size=36).shift(LEFT * 3 + DOWN * 6),
]
subject_group = VGroup(*subjects).arrange(DOWN, buff=0.5).shift(RIGHT * 3)
arrow01 = Arrow(start=texts.get_bottom(), end=subtitle.get_top(), buff=0.1, color=YELLOW)
# 将箭头添加到场景中
self.add(arrow01)
# 创建箭头
arrows = []
for subject in subjects:
arrow = Arrow(start=texts.get_bottom(), end=subject.get_top(), buff=0.1, color=YELLOW)
arrows.append(arrow)
# 添加元素到场景中
#self.play(Write(title), Write(subtitle))
#self.wait(1)
for arrow, subject in zip(arrows, subjects):
self.play(Create(arrow), Write(subject))
self.wait(0.5)
self.wait(2)
# 运行命令: manim -pql your_script.py LinearAlgebraDiagram
运行结果中发现,箭头向量的出发点是主标题的中心点,结束点也是副标题的中心点。这不是我们想要的结果。接下来我们在修改修改
解释代码
这段代码使用Manim库创建了一个线性代数的动画场景。首先,创建了一个包含主标题和副标题的文本对象,并将副标题放置在主标题的下方。然后计算了主标题和副标题的宽度,并根据最大宽度调整它们的位置,使它们居中显示在屏幕上。
接着创建了一组学科文本对象,并按照一定的顺序排列在主标题和副标题的右侧。然后创建了一个从主标题指向副标题的箭头,并将箭头添加到场景中。接着循环创建了一系列从主标题指向各个学科文本的箭头,并逐步显示每个箭头和对应的学科文本。
第二步:
调整箭头响亮的出发和结束点
from manim import *
class LinearAlgebraDiagram13(Scene):
def construct(self):
# 创建中心文本
title = Text("Linear Algebra", font_size=42).set_color(WHITE)
subtitle = Text("线 性 代 数", font_size=42)
# 将副标题移动到主标题的下方,并且左边对齐
subtitle.next_to(title, DOWN, buff=0) # 把副标题紧挨在主标题下方
# 获取标题和副标题的宽度
title_width = title.width
subtitle_width = subtitle.width
# 计算最大宽度,并根据最大宽度调整文本位置
max_width = max(title_width, subtitle_width)
# 计算文本居左对齐的位置
title.shift(RIGHT * (max_width - title_width) / 2)
subtitle.shift(RIGHT * (max_width - subtitle_width) / 2)
# 使用VGroup将它们组合并移动整个组合
texts = VGroup(title, subtitle).shift(4 * LEFT)
self.play(Write(texts)) # 显示文本组合
# 创建学科文本
subjects = [
Text("Computer science", font_size=36),
Text("Physics", font_size=36),
Text("Electrical engineering", font_size=36),
Text("Mechanical engineering", font_size=36),
Text("Statistics", font_size=36),
]
# 将科目文本左对齐并分别位置
for i, subject in enumerate(subjects):
subject.next_to(texts, DOWN, buff=0.5) # 将每个学科文本放在文本组合的下方
subject.shift(DOWN * (i + 1))
subject_group = VGroup(*subjects).shift(RIGHT *5+5*UP) # 将所有学科文本组合一起
# 创建箭头
arrows = []
for subject in subjects:
arrow = Arrow(start=texts.get_right(), end=subject.get_left(), buff=0.25, color=YELLOW)
arrows.append(arrow)
# 将箭头添加到场景中
for arrow, subject in zip(arrows, subjects):
self.play(Create(arrow), Write(subject))
self.wait(0.5)
self.wait(2)
运行结果:
运行结果中我们发现,箭头响亮的起始点正好对齐。但是,副标题没对齐
解释代码:
这段代码使用Manim库创建了一个线性代数的动画场景。首先,创建了一个包含主标题和副标题的文本对象,并将副标题放置在主标题的下方。然后计算了主标题和副标题的宽度,找到它们中较大的宽度作为最大宽度,然后调整文本位置使它们居中显示在屏幕左侧。
接着创建了一组包含不同学科名称的文本对象,并根据索引位置逐个放置在主标题和副标题的下方。然后将所有学科文本组合在一起,并将整个组合向右移动5个单位,向上移动5个单位。
接下来创建了一系列从主标题向各个学科文本的箭头,每个箭头的起点是主标题的右侧,终点是对应学科文本的左侧,并设置了箭头的样式为黄色。最后,循环逐个显示每个箭头和对应的学科文本,并在每次显示后等待0.5秒,最后等待2秒后动画结束。
第三步:大功告成
from manim import *
class LinearAlgebraDiagram114(Scene):
def construct(self):
self.camera.background_color = "#2F4F14"
#"#ece6e2"
# 创建中心文本
title = Text("Linear Algebra", font_size=42).set_color(WHITE)
subtitle = Text("线性代数", font_size=42)
# 将副标题移动到主标题的下方,并且左边对齐
subtitle.next_to(title, DOWN, buff=0) # 把副标题紧挨在主标题下方
# 获取标题和副标题的宽度
title_width = title.width
subtitle_width = subtitle.width
# 计算最大宽度,并根据最大宽度调整文本位置
max_width = max(title_width, subtitle_width)
# 计算文本居左对齐的位置
title.shift(RIGHT * (max_width - title_width) / 2)
subtitle.shift(RIGHT * (max_width - subtitle_width) / 2)
# 使用VGroup将它们组合并移动整个组合
texts = VGroup(title, subtitle).shift(4.5 * LEFT)
self.play(Write(texts)) # 显示文本组合
# 创建学科文本
subjects = [
Text("计算机科学", font_size=36),
Text("物理学", font_size=36),
Text("电气工程", font_size=36),
Text("机械工程", font_size=36),
Text("建筑学", font_size=36),
Text("统计学", font_size=36),
Text("...等等", font_size=36),
]
# 将科目文本左对齐并分别定位
for i, subject in enumerate(subjects):
subject.align_to(texts, RIGHT) # 左对齐到文本组合的左边
subject.next_to(texts, DOWN, buff=0.9 + i * 1).shift(5*UP+8.5*RIGHT) # 将每个学科文本放在文本组合的下方,增加间隔
# 获取所有科目文本的最大宽度
max_subject_width = max(subject.width for subject in subjects)
# 将所有科目文本组合并左对齐
for subject in subjects:
subject.shift(LEFT * (max_subject_width - subject.width) / 2) # 左对齐所有科目文本
# 创建箭头
arrows = []
for subject in subjects:
arrow = Arrow(start=texts.get_right(), end=subject.get_left(), buff=0.25,stroke_width=2, color=BLUE_A)
arrows.append(arrow)
# 将箭头添加到场景中
for arrow, subject in zip(arrows, subjects):
self.play(Create(arrow), Write(subject))
self.wait(0.5)
self.wait(2)
# 如果需要运行此代码,请确保在支持的环境中执行。
运行结果:
我们发现,运行结果和我们想要的结果完美闭合。