不要撒谎 發表於 2025-11-26 20:13:00

Manim进阶:用背景图片让你的数学视频脱颖而出

<p>做<code>Manim</code>动画久了,你是否厌倦了那万年不变的黑色虚空?</p>
<p>很多初学者(甚至老手)都想给动画加个背景图,但往往会遇到两个问题:</p>
<ol>
<li><strong>怎么加</strong>? 是把图片放进去,还是设置相机?</li>
<li><strong>看不清</strong>! 背景花里胡哨,前面的文字公式瞬间“隐身”了。</li>
</ol>
<p>今天,我们就来揭开<code>Manim</code>动画中一个简单却强大的技巧--为动画添加背景。</p>
<p>通过几个小示例,分别演示两种完全不同的背景处理思路。</p>
<h1 id="1-舞台布景法">1. 舞台布景法</h1>
<p>使用<code>ImageMobject</code>类,这是最直观、最常用的方法。</p>
<p>它的<strong>逻辑</strong>是:背景图片只是舞台上的一个普通演员,只是它长得特别大,而且站得特别靠后。</p>
<p>这种方式的<strong>特点</strong>是:</p>
<ul>
<li>
<p><strong>高度灵活</strong>:背景就是个对象(<code>Mobject</code>),所以它可以动!你可以让背景旋转、平移、缩放,甚至改变颜色。</p>
</li>
<li>
<p><strong>层级管理</strong>:需要手动把它的 <code>z_index</code> 设低,或者最先添加它。</p>
</li>
</ul>
<p>下面的第一个示例中,实现一个简单的<strong>动态背景</strong>,操作<strong>背景</strong>和操作一般的<code>Mobject</code>是一样的。</p>
<pre><code class="language-python">class Method1ImageMobject(Scene):
    def construct(self):
      # 1. 加载图片(确保这个图片是存在的)
      bg = ImageMobject("./assets/紫色梦幻星空.jpg")

      # 2. 核心操作:撑满屏幕并允许超出
      # 我们把高度设为屏幕高度的 2 倍,这样才有移动的空间
      bg.scale_to_fit_height(config.frame_height * 2)

      # 3. 核心操作:放到最底层
      bg.set_z_index(-100)

      self.add(bg)

      # 前景物体
      text = Text("方法一:ImageMobject", font_size=40, color=WHITE)
      sub = Text("背景可以动!", font_size=24, color=YELLOW).next_to(text, DOWN)

      self.play(Write(text), FadeIn(sub))

      # 4. 演示优势:让背景缓慢移动
      self.play(bg.animate.shift(LEFT * 2), rate_func=linear)
      self.play(bg.animate.shift(UP * 2), rate_func=linear)
      self.play(bg.animate.shift(RIGHT * 2), rate_func=linear)
      self.play(bg.animate.shift(DOWN * 2), rate_func=linear)
      self.wait()
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/83005/202511/83005-20251126201219254-295433127.gif" alt="" loading="lazy"></p>
<p>下面的示例也很简单,就是显示一段简单的公式。</p>
<p>不过,大家可以比较看看,相比于默认的黑色背景,加一个学校的黑板背景,是不是更有亲和力?</p>
<pre><code class="language-python">class Method2ImageMobject(Scene):
    def construct(self):
      # 1. 加载图片
      bg = ImageMobject("./assets/黑板.jpg")

      # 2. 调整大小铺满屏幕
      bg.scale_to_fit_height(config.frame_height)
      bg.scale_to_fit_width(config.frame_width)

      # 3. 核心操作:放到最底层
      bg.set_z_index(-100)
      self.add(bg)

      # 前景物体
      math = MathTex(r"\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}")
      self.play(Write(math))
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/83005/202511/83005-20251126201219323-1348443726.gif" alt="" loading="lazy"></p>
<h1 id="2-主角光环法">2. 主角光环法</h1>
<p>除了上面两种,还有一种比较特殊的方式,也就是<code>BackgroundColoredVMobjectDisplayer</code>类。</p>
<p>它是一个<strong>负责渲染</strong>的类,专门处理一种特殊情况:<strong>当物体拥有“背景色描边”时,如何遮挡住它背后的东西</strong>。</p>
<p>我们通过 <code>set_background_stroke()</code> 来调用这个机制。</p>
<p>严格来说不是 <strong>“设置全屏背景”</strong>,而是 <strong>“给物体加一个局部背景(Matte)”</strong>,这是在花哨背景下生存的必备技能。</p>
<p>它的<strong>特点</strong>是:</p>
<ul>
<li><strong>局部遮挡</strong>:在文字或公式周围生成一圈不透明的轮廓。</li>
<li><strong>增强对比</strong>:专门用于解决“背景太花,文字看不清”的问题。</li>
</ul>
<p>下面的示例故意构造了一个混乱的背景,然后比较看看,这两个一样的公式,是不是加了局部背景的公式更加清晰。</p>
<pre><code class="language-python">class ReadableFormulaOnImage(Scene):
    def construct(self):
      # 1. 先设置一个很花的背景(这里为了演示,我们用随机噪点模拟一张复杂的图)
      # 实际使用中,请换成你的 image.jpg
      noise = Rectangle(width=16, height=10)
      noise.set_fill(color=, opacity=0.5)
      # 把它搞得乱一点
      for _ in range(20):
            line = Line(
                start=,
                end=,
                color=random_color(),
                stroke_width=5,
            )
            self.add(line)
      self.add(noise)

      # 2. 普通的文字(在花背景下很难看清)
      bad_text = MathTex(r"\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}")
      bad_text.shift(UP)

      # 3. 【核心技巧】使用 BackgroundColoredVMobject 机制
      # set_background_stroke 会给文字加一层“描边”
      # 这层描边是不透明的,会利用 Displayer 类遮挡住背景!
      good_text = MathTex(r"\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}")
      good_text.set_background_stroke(color=BLACK, width=8)# 黑色描边,宽度设大一点
      good_text.shift(DOWN)

      # 动画演示对比
      self.play(Write(bad_text))

      self.play(Write(good_text))# 清晰可见!
      self.wait()
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/83005/202511/83005-20251126201219235-1716559304.gif" alt="" loading="lazy"></p>
<h1 id="3-两种方式比较">3. 两种方式比较</h1>
<p>两种方式各有自己的应用场景,对比如下:</p>
<table>
<thead>
<tr>
<th>特性</th>
<th>舞台布景法</th>
<th>主角光环法</th>
</tr>
</thead>
<tbody>
<tr>
<td>本质</td>
<td>场景中的一个巨大物体</td>
<td>物体自身的描边属性</td>
</tr>
<tr>
<td>主要用途</td>
<td>动态背景、视差滚动、多层背景</td>
<td>高亮主体、对抗花哨背景</td>
</tr>
<tr>
<td>动画能力</td>
<td>⭐⭐⭐⭐⭐ (极强)</td>
<td>⭐⭐⭐ (跟随物体运动)</td>
</tr>
<tr>
<td>代码复杂度</td>
<td>中 (需手动调大小/层级)</td>
<td>低 (一行设置)</td>
</tr>
<tr>
<td>文档对应</td>
<td><code>Mobject </code>类</td>
<td><code>BackgroundColoredVMobjectDisplayer</code></td>
</tr>
<tr>
<td>最佳场景</td>
<td>漂浮的云、移动的星空</td>
<td>字幕、复杂背景下的公式</td>
</tr>
</tbody>
</table>
<h1 id="4-总结">4. 总结</h1>
<p>简单来说,如果你想做一段电影感的片头,背景需要缓慢推移,请用 <strong>舞台布景法</strong>;</p>
<p>如果你发现文字看不清了,请使用 <strong>主角光环法</strong> (<code>set_background_stroke</code>) 给文字加个 <strong>“光环”</strong>。</p><br><br>
来源:https://www.cnblogs.com/wang_yb/p/19274531
頁: [1]
查看完整版本: Manim进阶:用背景图片让你的数学视频脱颖而出