用不同颜色来动画化一条线

5

我正在尝试为演示文稿制作动画数据。我尝试使用Python的animation包来完成。我的目标大致相当于http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/中的第一个示例。

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [], lw=2)

# initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    return line,

# animation function.  This is called sequentially
def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    line.set_data(x, y)
    return line,

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                           frames=200, interval=20, blit=True)

我刚开始学习Python,所以很难理解发生了什么。对我来说,似乎init()和animate(i)都没有修改它们返回的内容。此外,它们正在修改的对象line(而不是line之前已声明)。

无论如何,我想做的是将数据(在这种情况下是正弦波)分段着色。0到1之间为蓝色,1到1.5之间为红色,1.5到2之间再次为蓝色。我尝试了许多方法,但无法实现。我尝试让这些函数返回整个图形,而不仅仅是线条,希望它们会刷新预览图并绘制我绘制的组合线条,但无济于事。

在这个框架中,我该怎么样才能动画显示由不同颜色的线段组成的线条?

1个回答

8
要绘制一条属性沿着它变化的线,请使用LineCollection。示例在这里这里。要使用LineCollection制作动画,请参见示例。
要回答上面代码中的东西如何工作,在animate()中,您正在使用line.set_data(x,y)重置线x,y属性。然后,函数将(line,)集合返回给Matplotlib,Matplotlib必须在每个帧更新它们。
这是我认为你要找的内容(仅在最后一个调用中支持平台时启用blit=true):
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
from matplotlib.collections import LineCollection
from matplotlib.colors import ListedColormap, BoundaryNorm

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))

cmap = ListedColormap(['b', 'r', 'b'])
norm = BoundaryNorm([0, 1, 1.5, 2], cmap.N)

line = LineCollection([], cmap=cmap, norm=norm,lw=2)
line.set_array(np.linspace(0, 2, 1000))
ax.add_collection(line)

# initialization function: plot the background of each frame
def init():
    line.set_segments([])
    return line,

# animation function.  This is called sequentially
def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    points = np.array([x, y]).T.reshape(-1, 1, 2)
    segments = np.concatenate([points[:-1], points[1:]], axis=1)
    line.set_segments(segments)
    return line,

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                           frames=200, interval=20)

enter image description here


非常感谢。我之前不知道有LineCollection这个函数。 - Mathusalem
1
我理解这行代码是属于图形的一部分,现在它是由多个线段组成的。但是我该如何在animate的定义中修改它呢?我想要在每次迭代时更新BoundaryNorm和ListedColormap,但我不能在animate的定义中声明line = ...。有没有一种方法可以直接更新线条本身及其参数,而不仅仅是其中的内容?如果我想要这样做,那么我是否必须更新整个图形,而不仅仅是线条? - Mathusalem
1
使用 line.set_cmapline.set_norm。而且你不必更新整个图形。 - gg349
谢谢!我试图在动画中简单更新cmap,认为“所有东西都是在Python中引用的”。我想我需要读一本书。非常感谢您的帮助,现在它运行得很好。 - Mathusalem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接