Python中如何引用列表内Polygon并变换放回以优化多边形动画?
问题原因
plt.fill()返回的是包含单个Polygon实例的列表,所以你的poly列表里每个元素都是列表,不是Polygon对象,调用set_transform自然会触发AttributeError。
正确实现方案
要优化大量多边形的动画性能,推荐两种高效实现方式:
方式1:直接存储单个Polygon对象
直接创建patches.Polygon实例,添加到坐标轴后存入列表,后续直接操作这些实例的变换:
import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.patches as patches from matplotlib.animation import FuncAnimation n_poly = 10 poly = [] fig = plt.figure(frameon=False) fig.set_size_inches(2.0, 2.0) ax = plt.axes(xlim=(-2, 3), ylim=(-2, 3)) # 调整坐标轴范围防止图形跑出视野 # 定义正方形顶点 x_profile = [0, 1, 1, 0] y_profile = [0, 0, 1, 1] vertices = np.array([x_profile, y_profile]).T for i in range(n_poly): # 创建Polygon对象,设置初始位置偏移 polygon = patches.Polygon(vertices + [i*0.5, i*0.5], closed=True, facecolor=f"C{i}") ax.add_patch(polygon) poly.append(polygon) # 动画更新函数:每一帧更新旋转角度 def update(frame): angle = frame * 5 # 每帧旋转5度 for polygon in poly: # 构建旋转变换,结合坐标轴的默认变换(避免位置偏移) rotation = mpl.transforms.Affine2D().rotate_deg(angle) + ax.transData polygon.set_transform(rotation) return poly # 启动动画 ani = FuncAnimation(fig, update, frames=72, interval=50, blit=True) plt.show()
方式2:使用PatchCollection批量处理(更高效)
当多边形数量很多时,用PatchCollection可以批量管理和更新,性能更优:
import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.patches as patches from matplotlib.collections import PatchCollection from matplotlib.animation import FuncAnimation n_poly = 10 patches_list = [] fig = plt.figure(frameon=False) fig.set_size_inches(2.0, 2.0) ax = plt.axes(xlim=(-2, 3), ylim=(-2, 3)) # 定义正方形顶点 x_profile = [0, 1, 1, 0] y_profile = [0, 0, 1, 1] vertices = np.array([x_profile, y_profile]).T for i in range(n_poly): polygon = patches.Polygon(vertices + [i*0.5, i*0.5], closed=True) patches_list.append(polygon) # 创建PatchCollection并添加到坐标轴 collection = PatchCollection(patches_list, cmap="tab10") collection.set_array(np.arange(n_poly)) # 给每个多边形分配颜色 ax.add_collection(collection) # 动画更新函数 def update(frame): angle = frame * 5 # 批量更新每个patch的变换 for i in range(len(collection._transforms)): rotation = mpl.transforms.Affine2D().rotate_deg(angle) + ax.transData collection._transforms[i] = rotation return [collection] ani = FuncAnimation(fig, update, frames=72, interval=50, blit=True) plt.show()
关键注意点
- 旋转变换需要和
ax.transData结合,否则图形会以原点为中心旋转,且位置可能偏离预期 - 使用
FuncAnimation的blit=True可以大幅提升动画性能,只更新变化的部分 - 避免每一帧重新创建多边形,复用初始化的实例是优化性能的核心
内容的提问来源于stack exchange,提问作者user20787420
相关产品推荐
相关产品推荐

