matplotlib만 있으면 별도의 전문 라이브러리 없이도 간단한 코드로 입체적인 3D 애니메이션을 구현할 수 있습니다. 이번 글에서는 시간의 흐름에 따라 곡선이 그려지는 3D 궤적 애니메이션을 FuncAnimation 클래스를 활용해 단계별로 만들어 보겠습니다.
구현 절차
- 필수 패키지 임포트 − 3D 애니메이션을 위해서는 mpl_toolkits.mplot3d의
Axes3D와matplotlib.animation모듈이 필요합니다. - 그림 크기 설정 − figure 크기를 지정하고 서브플롯 사이 및 주변 여백을 자동으로 조정합니다.
- 데이터 생성 − numpy를 이용해 t, x, y 좌표 데이터 포인트를 만듭니다.
- figure 생성 − 새 figure를 생성하거나 기존 figure를 활성화합니다.
- 3D 축 가져오기 − Axes3D 인스턴스를 통해 3차원 좌표계를 확보합니다.
- 축 숨기기 −
axis('off')로 축을 제거해 깔끔한 화면을 연출합니다. - 선 그리기 − 준비된 데이터를 이용해 선(line)을 플로팅합니다.
- 애니메이션 생성 − animate 함수를 프레임마다 반복 호출하며 애니메이션을 구성합니다.
- 결과 표시 −
show()메서드로 완성된 애니메이션을 화면에 출력합니다.
전체 예제 코드
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D
plt.rcParams["figure.figsize"] = [7.00, 3.50]
plt.rcParams["figure.autolayout"] = True
def animate(num, data, line):
colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd',
'#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']
line.set_color(colors[num % len(colors)])
line.set_alpha(0.7)
line.set_data(data[0:2, :num])
line.set_3d_properties(data[2, :num])
return line
t = np.arange(0, 20, 0.2)
x = np.cos(t) - 1
y = 1 / 2 * (np.cos(2 * t) - 1)
data = np.array([x, y, t])
N = len(t)
fig = plt.figure()
ax = Axes3D(fig)
ax.axis('off')
line, = plt.plot(data[0], data[1], data[2], lw=7, c='red')
line_ani = animation.FuncAnimation(fig, animate, frames=N,
fargs=(data, line),
interval=50, blit=False)
plt.show()
코드 핵심 포인트
animate(num, data, line)함수는 프레임 번호(num)를 받아 그 순간까지의 데이터만 잘라내어 선을 업데이트합니다.- 미리 정의된 10가지 색상 리스트를 프레임마다 순환 적용해 곡선의 색이 계속 변하도록 했습니다.
set_data()는 x, y 좌표를,set_3d_properties()는 z 좌표를 갱신하는 3D 전용 메서드입니다.interval=50은 프레임 간 지연 시간(ms),frames=N은 총 프레임 수를 의미합니다.
실행 결과
위 코드를 실행하면 빨간색 곡선이 3차원 공간에서 점진적으로 그려지는 애니메이션이 출력됩니다. 매 프레임마다 선의 색상이 바뀌면서 곡선이 시간축(z축) 방향으로 나선형으로 뻗어 나가는 모습을 확인할 수 있습니다.


참고 사항
Axes3D(fig) 방식은 구버전 호환용이며, 최신 matplotlib(3.4 이상)에서는 fig.add_subplot(projection='3d') 사용이 권장됩니다. 또한 Jupyter Notebook 환경에서는 애니메이션이 표시되지 않을 수 있으므로, %matplotlib notebook 또는 HTML(line_ani.to_jshtml())을 활용하면 편리하게 결과를 확인할 수 있습니다.