manim 101:如何用 manim 画一个 2D 防火墙
October 12, 2024807 words, 5 min read
- Authors
- @SLIPPERTOPIA
近日做视频需要绘制一个防火墙,但苦于对动画制作不熟,于是用 manim (3b1b 大神做视频时用的动画库)绘制了一个简易、2D 版本。 过程中也是一边问 AI,一边测试,学了不少新知识,这里简单记录一下。
以上 gif 对应的详细代码参见 firewall.py
简单实现
实现思路很简单,通过继承 VGroup
类,在 self.submobjects
中添加若干砖块(bricks),就实现了一个简单的防火墙。
VGroup
是 Mobject
的子类,后者是 manim 中所有可渲染图形的基类,可以说是 manim 中核心的一个概念。通过 Mobject 可以把多个对象组织在一起,再把它作为一个整体进行操作(旋转、移动、变形等),大大简化复杂动画的创建。
以上 gif 中防火墙的变色、旋转、移动就是通过这个逻辑实现的。
from manim import *
import random
from manima.mobjects import MediaMobject, HandDrawnArrow
class Firewall(VGroup):
def __init__(
self,
num_bricks_x=4,
num_bricks_y=6,
brick_width=1,
brick_height=0.5,
brick_spacing_x=0.1,
brick_spacing_y=0.1,
corner_radius=0.05,
fill_color=BLUE,
outline_color=WHITE,
rotation_x=0, # X轴旋转
rotation_y=0, # Y轴旋转
rotation_z=0, # Z轴旋转
**kwargs
):
super().__init__(**kwargs)
self.fill_color = fill_color
self.outline_color = outline_color
# Create a list of all possible brick positions
positions = [(i, j) for j in range(num_bricks_y)
for i in range(num_bricks_x)]
# Shuffle the positions to randomize brick creation order
random.shuffle(positions)
for i, j in positions:
text = f"{i*j}"
brick_group = self.create_brick(
brick_width, brick_height, corner_radius, text)
brick_group.shift(
RIGHT * i * (brick_width + brick_spacing_x) +
UP * j * (brick_height + brick_spacing_y)
)
self.add(brick_group)
self.center()
self.rotate(rotation_x, axis=RIGHT) # 绕X轴旋转
self.rotate(rotation_y, axis=UP) # 绕Y轴旋转
self.rotate(rotation_z, axis=OUT) # 绕Z轴旋转
def create_brick(self, brick_width, brick_height, corner_radius, text):
brick_group = VGroup()
brick = RoundedRectangle(
width=brick_width,
height=brick_height,
corner_radius=corner_radius,
fill_color=self.fill_color,
fill_opacity=1,
stroke_color=self.outline_color,
stroke_width=2
)
number = Text(text, font_size=24, color=WHITE)
number.set_z_index(1)
number.move_to(brick.get_center())
brick_group.add(brick, number)
return brick_group
def set_color(self, color):
for brick_group in self.submobjects:
brick_group[0].set_fill(color)
return self
def set_text(self, text):
for brick_group in self.submobjects:
brick_group[1] = Text(text, font_size=24, color=WHITE)
brick_group[1].move_to(brick_group[0].get_center())
return self
设置属性
比如文本与颜色,这点还是挺好实现的,通过重写 set_text
和 set_color
方法即可。
但动作的设计有点难,比如我想让砖块逐个旋转到某个角度,就不是很好实现。
# not working
def rotate_brick(self, angle):
for brick_group in self.submobjects:
brick_group[0].rotate(angle)
manim 命令行常用参数
- 播放选项:
-p
或--play
: 在成功渲染后自动播放生成的视频。-a
或--write_all
: 渲染提供文件中的所有场景,而不仅仅是第一个场景。
- 质量与分辨率选项:
-q
或--quality [l|m|h|p|k]
: 设置视频质量。l
: 低质量(480p)m
: 中等质量(720p)h
: 高质量(1080p)p
: 产品质量(大概是高清质量)k
: 4K 质量
-r
或--resolution WIDTH,HEIGHT
: 手动设置视频的输出分辨率。 E.g.,-pqp -r 1920,1080
即输出一段高质量(60fps) 1080p 质量的视频。
- 文件与输出设置:
-o
或--output_file FILE_NAME
: 自定义输出文件名。--format [mp4|gif|png]
: 指定输出格式,可以是视频、GIF 或静态图像。
- 帧与速率控制:
--fps FPS
: 设置输出视频的帧率。-n
或--from_animation_number N
: 从特定的动画序号开始渲染。
- 日志与输出控制:
--log_level [DEBUG|INFO|WARNING|ERROR|CRITICAL]
: 设置日志输出的详细级别。--progress_bar [DISPLAYED|LEAVE|HIDDEN]
: 控制进度条的显示情况。
- 其他有用选项:
--media_dir DIR
: 设置媒体目录路径,用于存放生成的视频和图像。--config_file FILE
: 指定不同的配置文件运行 manim。