matplotlib升级到3.3.4后FuncAnimation缩放后自动回退问题如何解决
解决方案
问题原因
matplotlib 3.3及以上版本调整了ax.plot()方法的默认行为:每次调用plot新增绘图元素时,会自动重置坐标轴的自动缩放状态为开启,即使用户之前通过手动缩放/平移操作关闭了自动缩放,也会被重新打开,触发全量数据范围适配,就会出现缩放后立即回弹的问题。
修复方案
只需要在动画帧更新逻辑中,先保存当前坐标轴的自动缩放状态,绘图后恢复原有状态,再根据原有状态决定是否要适配新数据范围即可,修改后的完整代码如下:
import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from random import random def test(): """Test live matplotlib animation""" fig, (ax1, ax2) = plt.subplots(2, 1) def animate(i): x = random() # Fake sensor 1 y = 10 * random() + 3 # Fake sensor 2 # 保存当前坐标轴的自动缩放状态 ax1_auto = ax1.get_autoscale_on() ax2_auto = ax2.get_autoscale_on() ax1.plot(i, x, 'ok') ax2.plot(i, y, 'ob') # 恢复原有自动缩放状态,避免plot操作重置状态 ax1.set_autoscale_on(ax1_auto) ax2.set_autoscale_on(ax2_auto) # 仅当自动缩放原本为开启状态时,才适配新数据范围 if ax1_auto: ax1.autoscale_view() if ax2_auto: ax2.autoscale_view() ani = FuncAnimation(fig, animate, interval=100) plt.show() return ani
修改后即可恢复3.2.2版本的交互逻辑:初始阶段自动适配新增数据调整坐标轴范围,用户手动缩放/平移后,自动保持在选定范围,不会回弹。
性能优化建议
上述示例每次调用plot都会新增一个绘图对象,数据量增大后会出现明显卡顿,建议改为更新单条线的数据的方式实现实时打点,性能提升非常明显:
import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from random import random def test(): """Test live matplotlib animation with better performance""" fig, (ax1, ax2) = plt.subplots(2, 1) # 初始化线条对象和数据缓存 line1, = ax1.plot([], [], 'ok') line2, = ax2.plot([], [], 'ob') x_cache = [] y1_cache = [] y2_cache = [] def animate(i): x_cache.append(i) y1_cache.append(random()) y2_cache.append(10 * random() + 3) # 更新线条数据 line1.set_data(x_cache, y1_cache) line2.set_data(x_cache, y2_cache) # 同样的自动缩放控制逻辑 ax1_auto = ax1.get_autoscale_on() ax2_auto = ax2.get_autoscale_on() ax1.set_autoscale_on(ax1_auto) ax2.set_autoscale_on(ax2_auto) if ax1_auto: ax1.autoscale_view() if ax2_auto: ax2.autoscale_view() ani = FuncAnimation(fig, animate, interval=100) plt.show() return ani
内容的提问来源于stack exchange,提问作者Olivier Vincent
相关产品推荐
相关产品推荐

