教你画积分动画

创作背景

今天看到群里有群提问,如下图
教你画积分动画
只是为了巩固上一篇使用Matplotlib制作动画的知识,然后学习制作动态直方图,写这篇文章记录一下。
如果你觉得我的文章不错,可以给我点个赞评论收藏一站式(☆▽☆)。如果您订购关注,这并非不可能🤗。
请参与文末投票。如有不足之处,请在评论区提出,不胜感激。

知识回顾

查看使用 FuncAnimation 创建曲线动画的步骤(有关详细信息,请参阅本文):

  1. 设置画布。
  2. 创建一个列表来保存点坐标。
  3. 构建更新功能。
  4. 使用 FuncAnimation 启动动画。

新知识

上一个是曲线画,这次想加个直方图,所以来这里学一波。

这段代码的思路是:记录一系列路径点的坐标,通过移动到指定点并在两点之间画一条直线来画一列。这个思路可以借鉴。

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

我的思路

  1. 首先还是要导入需要的包。 import numpy as npimport matplotlib.path as pathimport matplotlib.pyplot as pltimport matplotlib.patches as patchesfrom matplotlib.animation import FuncAnimation
    其中, numpy 用来生成点数据, path 是用来生成路径, patches 通过路径绘制图像。
  2. 然后还是设置一下画布,设置 x 和 y 轴的范围。 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 + 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 也同样添加四个动作。
    然后生成路径并显示。
  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 = 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

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2022年3月14日 上午11:42
下一篇 2022年3月14日 下午12:01

相关推荐