手把手教你绘制积分动图

创作背景

今天在群里看到有群有问问题,如下图所示
在这里插入图片描述
正好巩固一下上上一篇利用 Matplotlib 制作动图的知识,再学习一下制作动态柱状图,写下此篇以记录。
如果觉得我这篇文章写的好的话,能不能给我 点个赞评论收藏 一条龙(☆▽☆)。如果要点个 关注 的话也不是不可以🤗。
请各位参加一下文末的 投票 哦,如果 有什么不足之处,还 请各位大佬在评论区提出,不胜感激。

知识回顾

回顾一下使用 FuncAnimation 制作曲线动图的步骤(详情请见这篇文章):

  1. 设置画布。
  2. 创建列表以保存点坐标。
  3. 构建更新函数。
  4. 使用 FuncAnimation 启动动画。

新的知识

上一篇是 曲线绘图 ,这次要加上 柱状图 ,于是我来到了 这里 学习一波。

这个代码的思路是:记录一连串路径点的坐标 ,通过 移动到指定点两点间绘制直线 来绘制柱子,可以借鉴这个思路。

从代码中可得,我们要使用 matplotlib.path.Path 记录绘制矩形的路径及方法,使用 matplotlib.patches.PathPatch 将路径绘制出来,最后使用 ax.add_patch() 将其在画布上显示出来。

我的思路

  1. 首先还是要导入需要的包。

    import numpy as np
    import matplotlib.path as path
    import matplotlib.pyplot as plt
    import matplotlib.patches as patches
    from matplotlib.animation import FuncAnimation
    

    其中,numpy 用来生成点数据,path 是用来生成路径,patches 通过路径绘制图像。

  2. 然后还是设置一下画布,设置 xy 轴的范围。

    fig, ax = plt.subplots()
    
    ax.set_xlim(0, 1.1)
    ax.set_ylim(0, 3)
    
  3. 初始化曲线和数据,以保存点的坐标和路径动作。

    ln = plt.plot([], [], 'ro')
    
    codes = []
    verts = np.empty((0, 2), np.float64)
    points = np.empty((0, 2), np.float64)
    

    其中,codes 保存路径动作,verts 保存路径点坐标,points 保存曲线点坐标。

  4. 设置更新函数。

    func = lambda x: x**3 + 1
    
    def 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 也同样添加四个动作。

    然后生成路径并显示。

  5. 启动动画

    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 = [[frame, func(frame)]]
        verts = [[frame, 0], [frame, func(frame)], [frame+dx, func(frame)], [frame+dx, 0]]
        ln[0].set_data(list(zip(*points)))

        codes = [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 的小伙伴可以 私信我 进群哦。

以上就是我要分享的内容,因为 学识尚浅会有不足,还 请各位大佬指正
有什么问题也可在评论区留言。
在这里插入图片描述

  • 14
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值