首页 / 文档中心 / 进阶

Manim 图与网络:Graph 类画树、网络图与布局算法切换动画

发布于 2026-11-02 · 进阶系列 · 约 4 分钟读完 · 中文正文 + English TL;DR
▶ 渲染效果实录(manim 渲染输出,代码见正文,可直接复现)
English TL;DR

Manim CE's Graph class turns vertex/edge lists into laid-out network diagrams with one call, and animates between layouts. This guide covers the built-in layouts — spring (force-directed, seedable for reproducibility), circular, kamada_kawai, planar, partite (for bipartite graphs), random, and tree with root_vertex — plus per-vertex and per-edge styling through vertex_config/edge_config, label control, degree-based sizing, highlighting vertices and edges mid-animation, and the change_layout() animation that morphs an entire network from one arrangement to another. Also: adding/removing vertices and edges dynamically, curving multiple edges between the same pair, and self-loops. A complete runnable example builds a small social network, walks a BFS frontier with lagged highlights, then re-lays the graph as a tree.

一个调用出一张图

from manim import *

class GraphTour(Scene):
    def construct(self):
        g = Graph(
            [1, 2, 3, 4, 5, 6],
            [(1, 2), (2, 3), (3, 4), (4, 5), (5, 1), (2, 6), (3, 6)],
            layout="spring", layout_config={"seed": 2},
            labels=True,
            vertex_config={"radius": 0.28, "color": BLUE,
                           "fill_opacity": 1},
            edge_config={"stroke_width": 2.5},
        )
        self.play(Create(g), run_time=2)
        self.wait()

顶点列表 + 边列表,Graph 自动完成布局计算、顶点圆点绘制、边连线裁剪。这是 0.15+ 的正式 API,比早期手画 Line + Dot 省一半代码。

内置布局算法

layout效果常用参数
spring力导向(networkx 风格)seed 固定随机结果
kamada_kawai更均匀的力导向—
circular顶点排成一圈—
planar无边交叉的平面布局—
partite分层排列(二部图)partitions
tree层次树root_vertex
random随机散点seed

布局切换:最好看的图动画

self.play(g.animate.change_layout("circular"), run_time=2)
self.play(g.animate.change_layout(
    "tree", layout_config={"root_vertex": 1}), run_time=2)

同一张图在"力导向 → 环形 → 树"之间平滑变形,是讲图论算法(同一结构、不同视角)的利器。

顶点/边的个性化配置

g = Graph(
    [1, 2, 3, 4],
    [(1, 2), (2, 3), (3, 4), (1, 3)],
    vertex_config={
        1: {"color": RED},                 # 指定顶点单独配色
        "default": {"color": BLUE},        # 其余默认
    },
    edge_config={
        (1, 3): {"color": YELLOW, "stroke_width": 4},
    },
)

按度数缩放顶点(社交网络风格):

degrees = {v: 0 for v in vertices}
for a, b in edges:
    degrees[a] += 1; degrees[b] += 1
g = Graph(vertices, edges,
          vertex_config={v: {"radius": 0.2 + 0.08 * degrees[v]}
                         for v in vertices})

动画中高亮:遍历的可视化

# 高亮单点 / 单边
self.play(g.vertices[2].animate.scale(1.6).set_color(YELLOW))
self.play(g.edges[(1, 2)].animate.set_stroke(YELLOW, width=5))

# BFS 逐层扩散: LaggedStart 按发现顺序点亮
order = [1, 2, 3, 6, 4, 5]   # 你的遍历顺序
self.play(LaggedStart(
    *[g.vertices[v].animate.set_color(TEAL) for v in order],
    lag_ratio=0.4))

0.18+ 还有一步到位的 g.animate.highlight_vertices([...]) / highlight_edges(用 create_highlighted 风格),旧版本用上面的手动写法即可。

动态增删点边

self.play(g.animate.add_vertices(7))
self.play(g.animate.add_edges((6, 7)))
self.play(g.animate.remove_edges((1, 2)))

多重边与自环:边写成 ((1, 2),)(元组套元组)允许两点间多条边;自环直接 (1, 1)。新版本会自动弯曲避免重叠。

与 networkx 联动

Graph 的 layout 参数背后就是 networkx:复杂布局可以自己算好坐标再喂给 manim:

import networkx as nx
nxg = nx.karate_club_graph()
g = Graph.from_networkx(nxg, layout="spring",
                        layout_config={"seed": 1})