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

Matplotlib多子图动画添加共享X轴描述/标题的实现问题

How to Add Dynamic Shared Step Text to Matplotlib Subplot Grid Animations

I’ve got a clean solution for your problem—instead of relying on subplot axes to add dynamic text, we’ll use the figure-level text object that stays anchored to the entire plot, updating its content every frame. Here’s how to implement it:

Key Idea

Instead of trying to hack subplot axes for shared text, we create a single text element directly on the figure itself. We’ll track this text by a unique label so we can update its content each frame, rather than creating new text objects every time. This ensures the text stays in a consistent, shared position (like the bottom center of the figure) and updates seamlessly with the animation.

Modified Code

Here’s the updated version of your code with this solution integrated:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import ArtistAnimation, PillowWriter
plt.rcParams['animation.html'] = 'jshtml'

def make_grid(fig, X, step, description=None, labels=None, title_fmt="label: {}", cmap='gray', ncols=3, colors=None):
    L = len(X)
    nrows = -(-L // ncols)
    frame_plot = []
    
    # Update or create the shared step text
    step_text = None
    # Look for existing text with our unique label
    for text in fig.texts:
        if text.get_label() == 'step_text':
            step_text = text
            break
    # Create text if it doesn't exist yet
    if not step_text:
        # Position at bottom center (adjust y-coordinate as needed)
        step_text = fig.text(
            0.5, 0.02, 
            f"step={step}", 
            ha='center', va='center', 
            fontsize=12, 
            label='step_text'
        )
    else:
        # Update text content for the current frame
        step_text.set_text(f"step={step}")
    frame_plot.append(step_text)
    
    # Create subplots as before
    for i in range(L):
        ax = plt.subplot(nrows, ncols, i + 1)
        im = ax.imshow(X[i].squeeze(), cmap=cmap, interpolation='none')
        if labels is not None:
            color = 'k' if colors is None else colors[i]
            ax.set_title(title_fmt.format(labels[i]), color=color)
        ax.set_xticks([])
        ax.set_yticks([])
        frame_plot.append(im)
    return frame_plot

def animate_step(X):
    return X ** 2

n_splots = 6
X = np.random.random((n_splots,32,32,3))
Y = X
X_t = []
for i in range(10):
    Y = animate_step(Y)
    X_t.append((Y, i))

# Initialize the figure first
fig = plt.figure()
frames = []
for X, step in X_t:
    frame = make_grid(fig, X, step, labels=range(n_splots), title_fmt="target: {}")
    frames.append(frame)

anim = ArtistAnimation(fig, frames, interval=300, repeat_delay=8000, blit=True)
plt.close()
anim.save("test.gif", writer=PillowWriter())
anim

What Changed?

  1. Pass the figure to make_grid: We now explicitly pass the fig object so we can manage the global text element.
  2. Reusable text object: We check for an existing text element with the label step_text—if it exists, we update its content; if not, we create it once. This avoids cluttering the figure with duplicate text objects.
  3. Add text to frame elements: The text object is added to the frame_plot list, so ArtistAnimation knows to include it in the blitting/updating process.

Why This Is Better Than Your Temporary Fix

  • Stable position: The text is anchored to the figure, not a specific subplot, so it won’t shift if you change the number of rows/columns in your grid.
  • Cleaner code: No reliance on "last row middle axis" hacks—this is an intentional, maintainable approach.
  • Seamless updates: Blitting works correctly because we’re updating the existing text object instead of creating new ones each frame.

内容的提问来源于stack exchange,提问作者Kurt Willis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 08:52:36