更新
回想起来,我注意到我的第一次尝试是一种浪费的方法——蓝线仍然保留在内存中,我们只是不再看到它们(实际上,我们看到了——它们的颜色不是灰色而是灰蓝色)。因此,我们最好跟踪绘制的线并更改它们的颜色。
import matplotlib.pyplot as plt
import matplotlib.animation as anim
import numpy as np
fig = plt.figure()
ax = fig.gca(projection="3d")
#random data
np.random.seed(12345)
d3d = np.random.random((3, 12))
line_list = []
#number of line segments to retain in blue before greying them out
line_delay = 4
def init():
ax.clear()
#you can omit the fixed scales, then they will be automatically updated
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 1)
def update(i):
#initializing the plot, emptying the line list
if not i:
init()
line_list[:] = []
#set line color to grey if delay number is exceeded
if len(line_list)>=line_delay:
line_list[-line_delay].set_color("grey")
#plot new line segment
newsegm, = ax.plot(*d3d[:, i:i+2], "blue")
line_list.append(newsegm)
ani = anim.FuncAnimation(fig, update, init_func=init, frames = np.arange(d3d.shape[1]), interval = 300, repeat=True)
plt.show()
这种方法还有一个优点是我们可以轻松地调整它以更好地表示数据 - 例如,如果我们有很多数据,我们可以让它们淡化并移除所有不可见的线条:
import matplotlib.pyplot as plt
import matplotlib.animation as anim
import numpy as np
fig = plt.figure()
ax = fig.gca(projection="3d")
#random data
np.random.seed(12345)
d3d = np.random.random((3, 40))
#defines the number of disappearing line segments
max_length = 20
line_list = []
def init():
ax.clear()
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 1)
def update(i):
if not i:
init()
line_list[:] = []
else:
#if not the first line segment, change color to grey,
line_list[-1].set_color("grey")
#then reduce gradually the alpha value for all line segments
diff2max = max(0, max_length-len(line_list))
[x.set_alpha((j+diff2max)/max_length) for j, x in enumerate(line_list)]
#delete line segments that we don't see anymore to declutter the space
if len(line_list)>max_length:
del_line = line_list.pop(0)
del_line.remove()
#plot new segment and append it to the list
newsegm, = ax.plot(*d3d[:, i:i+2], "blue")
line_list.append(newsegm)
ani = anim.FuncAnimation(fig, update, init_func=init, frames = np.arange(d3d.shape[1]), interval = 300, repeat=True)
plt.show()
样本输出:
初步回答
如果单独绘制线条,可以用灰色线条覆盖之前的蓝色线条。
import matplotlib.pyplot as plt
import matplotlib.animation as anim
import numpy as np
fig = plt.figure()
ax = fig.gca(projection="3d")
#random data
np.random.seed(12345)
d3d = np.random.random((3, 10))
def init():
ax.clear()
#you can omit the fixed scales, then they will be automatically updated
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 1)
def update(i):
if not i:
init()
else:
ax.plot(*d3d[:, i-1:i+1], "grey") #plot old segment
ax.plot(*d3d[:, i:i+2], "blue") #plot new segment
ani = anim.FuncAnimation(fig, update, init_func=init, frames = np.arange(d3d.shape[1]-1), interval = 300, repeat=True)
plt.show()
样本输出: