class Circles:
def __init__(self, frames):
self.frames = frames
self.ds = 2.1
self.data = []
self.edge_data = []
self.xlims = [-0.5 * self.ds, 7.5 * self.ds]
self.ylims = [-7.5 * self.ds, 0.5 * self.ds]
t = np.linspace(np.pi / 2, -3 * np.pi / 2, frames)
for row in range(1, 8):
self.edge_data.append((np.cos(row * t) + self.ds * row, np.sin(row * t), f"C{row}"))
self.edge_data.append((np.cos(row * t), np.sin(row * t) - self.ds * row, f"C{row}"))
for row in range(1, 8):
for col in range(1, 8):
self.data.append((np.cos(row * t) + self.ds * row,
np.sin(col * t) - self.ds * col, f"C{(row - col + 1) % 8}"))
self.fig, self.ax = plt.subplots(figsize=(10, 10), constrained_layout=True)
def init(self):
self.axlines = []
for idx, (xdata, ydata, c) in enumerate(self.edge_data):
self.ax.plot(xdata, ydata, color=c, lw=3)
if idx % 2 == 0:
self.axlines.append(self.ax.plot([], [], lw=1, color='w', alpha=0.2)[0])
else:
self.axlines.append(self.ax.plot([], [], lw=1, color='w', alpha=0.2)[0])
self.edge_circs = [self.ax.plot([], [], 'wo', lw=0, mfc='w')[0] for _ in self.edge_data]
self.lines = [self.ax.plot([], [], color=c, lw=3)[0] for _, _, c in self.data]
self.circs = [self.ax.plot([], [], 'wo', lw=0, mfc='w')[0] for _ in self.data]
self.ax.set_facecolor('black')
self.ax.yaxis.set_visible(False)
self.ax.xaxis.set_visible(False)
self.ax.set_xlim(*self.xlims)
self.ax.set_ylim(*self.ylims)
self.artists = self.edge_circs + self.lines + self.circs + self.axlines
return self.artists
def update(self, idx):
for line, circ, (xdata, ydata, _) in zip(self.lines, self.circs, self.data):
line.set_data(xdata[:idx], ydata[:idx])
circ.set_data(xdata[idx], ydata[idx])
for j, ((xdata, ydata, _), circ, line) in enumerate(zip(self.edge_data, self.edge_circs, self.axlines)):
circ.set_data(xdata[idx], ydata[idx])
if j % 2 == 0:
line.set_data([xdata[idx], xdata[idx]], self.ylims)
else:
line.set_data(self.xlims, [ydata[idx], ydata[idx]])
return self.artists
circ = Circles(200)
def init():
return circ.init()
anim = FuncAnimation(circ.fig, circ.update, frames=circ.frames,
init_func=circ.init, blit=True, interval=50)
HTML(anim.to_html5_video())