You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Matplotlib中实现动画的平滑过渡效果?

问题

我想用Matplotlib创建动画,但当前可视化的美观性差:动画里后一帧数值会突兀替换前一帧,没有平滑过渡效果,这种动画只适合自用,公开演示观感不好。以下是Matplotlib官方文档里的直方图动画示例代码:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
np.random.seed(19680801)

HIST_BINS = np.linspace(-4, 4, 100)
data = np.random.randn(1000)
n, _ = np.histogram(data, HIST_BINS)


def prepare_animation(bar_container):

    def animate(frame_number):

        # simulate new data coming in
        data = np.random.randn(1000)
        n, _ = np.histogram(data, HIST_BINS)
        for count, rect in zip(n, bar_container.patches):
            rect.set_height(count)
        return bar_container.patches
    return animate


fig, ax = plt.subplots()
_, _, bar_container = ax.hist(data, HIST_BINS, lw=1,
                              ec="yellow", fc="green", alpha=0.5)
ax.set_ylim(top=55)
ani = animation.FuncAnimation(fig, prepare_animation(bar_container), 50,
                              repeat=False, blit=True)
plt.show()

这个示例的动画帧切换很突兀,参考flet库的平滑动画效果,Matplotlib能不能实现类似的平滑过渡?

解决方案

Matplotlib完全可以实现直方图的平滑过渡动画,核心思路是在前后两帧的直方图数值之间做线性插值,分多步完成高度更新,而不是直接跳变到目标值。

修改后的代码如下:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
np.random.seed(19680801)

HIST_BINS = np.linspace(-4, 4, 100)
data = np.random.randn(1000)
current_n, _ = np.histogram(data, HIST_BINS)
# 预存目标直方图数值,模拟多组新数据流入
target_histograms = [np.histogram(np.random.randn(1000), HIST_BINS)[0] for _ in range(50)]
# 每段平滑过渡的步数,数值越大过渡越平缓
transition_steps = 10

def prepare_animation(bar_container):
    current_idx = 0
    step = 0

    def animate(frame_number):
        nonlocal current_idx, step
        # 完成一段过渡后,切换到下一个目标直方图
        if step == 0:
            target_n = target_histograms[current_idx]
            current_idx = (current_idx + 1) % len(target_histograms)
        
        # 计算当前插值比例
        alpha = step / transition_steps
        # 线性插值得到当前帧的柱子高度
        interpolated_n = current_n * (1 - alpha) + target_n * alpha
        
        # 更新每个柱子的高度
        for count, rect in zip(interpolated_n, bar_container.patches):
            rect.set_height(count)
        
        step += 1
        # 重置步数,准备下一段过渡
        if step > transition_steps:
            step = 0
            global current_n
            current_n = target_n.copy()
        
        return bar_container.patches
    return animate


fig, ax = plt.subplots()
_, _, bar_container = ax.hist(data, HIST_BINS, lw=1, ec="yellow", fc="green", alpha=0.5)
ax.set_ylim(top=55)
# 总帧数 = 目标组数 × 过渡步数
ani = animation.FuncAnimation(fig, prepare_animation(bar_container), len(target_histograms)*transition_steps,
                              repeat=False, blit=True)
plt.show()

关键修改点说明:

  • 预先生成多组目标直方图数据,模拟连续的新数据流入场景
  • 引入transition_steps控制每两次数据更新之间的过渡帧数,数值越大过渡效果越平滑
  • 通过线性插值公式计算当前帧的柱子高度,让柱子从当前值逐步过渡到新数据的统计值
  • 完成一段过渡后,更新当前直方图基准值,为下一次过渡做准备

修改后,直方图柱子的高度会平滑变化,避免了原示例中突兀的帧跳变,适合用于公开演示场景。

内容的提问来源于stack exchange,提问作者Igor K.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 06:47:41