创作背景
今天看到群里有群提问,如下图
只是为了巩固上一篇使用Matplotlib
制作动画的知识,然后学习制作动态直方图,写这篇文章记录一下。
如果你觉得我的文章不错,可以给我点个赞
,评论
,收藏
一站式(☆▽☆)。如果您订购关注
,这并非不可能🤗。
请参与文末投票
。如有不足之处,请在评论区提出,不胜感激。
知识回顾
查看使用 FuncAnimation
创建曲线动画的步骤(有关详细信息,请参阅本文):
- 设置画布。
- 创建一个列表来保存点坐标。
- 构建更新功能。
- 使用 FuncAnimation 启动动画。
新知识
上一个是曲线画,这次想加个直方图,所以来这里学一波。
这段代码的思路是:记录一系列路径点的坐标,通过移动到指定点并在两点之间画一条直线来画一列。这个思路可以借鉴。
从代码中我们需要用matplotlib.path.Path
来记录绘制矩形的路径和方法,用matplotlib.patches.PathPatch
来绘制路径,最后用ax.add_patch()
在画布上显示。
我的思路
- 首先还是要导入需要的包。 import numpy as npimport matplotlib.path as pathimport matplotlib.pyplot as pltimport matplotlib.patches as patchesfrom matplotlib.animation import FuncAnimation
其中, numpy 用来生成点数据, path 是用来生成路径, patches 通过路径绘制图像。 - 然后还是设置一下画布,设置 x 和 y 轴的范围。 fig, ax = plt.subplots()ax.set_xlim(0, 1.1)ax.set_ylim(0, 3)
- 初始化曲线和数据,以保存点的坐标和路径动作。 ln = plt.plot([], [], ‘ro’)codes = []verts = np.empty((0, 2), np.float64)points = np.empty((0, 2), np.float64)
其中, codes 保存路径动作, verts 保存路径点坐标, points 保存曲线点坐标。 - 设置更新函数。 func = lambda x: x**3 + 1def update(frame): global points, verts, codes points = np.append(points, [[frame, func(frame)]], axis=0) verts = np.append(verts, [[frame, 0], [frame, func(frame)], [frame+1/50, func(frame)], [frame+1/50, 0]], axis=0) ln[0].set_data(list(zip(*points))) codes.extend([path.Path.MOVETO] + [path.Path.LINETO] * 3) barpath = path.Path(verts, codes) patch = patches.PathPatch(barpath, facecolor=’blue’, edgecolor=’yellow’, alpha=0.5) ax.add_patch(patch) return patch, ln[0],
其中, verts 要添加 4 个点的坐标,分别是矩形的四个顶点坐标, codes 也同样添加四个动作。
然后生成路径并显示。 - 启动动画ani = FuncAnimation(fig, update, frames=np.linspace(0, 1, 50), repeat=False, blit=True)# 保存# ani.save(‘test.gif’, writer=’imagemagick’, fps=10)plt.show()
参数就不细讲了,详见上一篇文章,如果在 jupyter 中绘制的话,记得要在代码框最前边加上 %matplotlib notebook 哦。
最后看一下效果:
看起来不错。
打包它
可以看出代码可以封装,封装的函数可以实现绘制任意函数的整体动画。
(当然,由于我代码能力的限制,这是一个粗略的版本,如果有大佬可以修改,能不能让我看一下)
代码显示如下:
%matplotlib notebook
import numpy as np
import matplotlib.path as path
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.animation import FuncAnimation
def create_gif(func, interval=[-1, 1, -1, 1], bins=50):
if not isinstance(interval, (list, np.array)):
raise ValueError(f'Input data "{interval}" is invalid.')
def update(frame):
global points, verts, codes
dx = (interval[1] - interval[0]) / bins
points = np.append(points, [[frame, func(frame)]], axis=0)
verts = np.append(verts, [[frame, 0], [frame, func(frame)], [frame+dx, func(frame)], [frame+dx, 0]], axis=0)
ln[0].set_data(list(zip(*points)))
codes.extend([path.Path.MOVETO] + [path.Path.LINETO] * 3)
barpath = path.Path(verts, codes)
patch = patches.PathPatch(barpath, facecolor='blue', edgecolor='yellow', alpha=0.5)
ax.add_patch(patch)
return patch, ln[0],
fig, ax = plt.subplots()
ax.axis(interval)
global points, verts, codes
codes = []
verts = np.empty((0, 2), np.float64)
points = np.empty((0, 2), np.float64)
ln = plt.plot([], [], 'ro')
global ani
ani = FuncAnimation(fig, update, frames=np.linspace(*interval[:2], bins), repeat=False, blit=True)
# ani.save('test.gif', writer='imagemagick', fps=10)
plt.show()
在:
- func就是要绘制动图的函数。
- interval是坐标轴范围。
- bins是要绘制的柱子个数。
做一个测试:
func = lambda x: x**3+1
create_gif(func, [0, 1.1, 0, 3])
和上面的结果一样,你也可以自己试试。
结尾
如果有朋友想一起学习python
,可以私信我
加入群。
以上就是我想分享的,因为我的知识还很浅薄,会有不足之处,请大家指正。
有什么问题可以在评论区留言。
版权声明:本文为博主lhys666原创文章,版权归属原作者,如果侵权,请联系我们删除!
原文链接:https://blog.csdn.net/lhys666/article/details/123451524