스트레인지 어트랙터

Strange attractor

단 몇 개의 수식을 수만 번 반복 계산해서 점을 찍으면 드러나는, 카오스 이론의 대표적인 나비 모양 궤적.

다른 이름: Clifford attractorChaotic attractor
···
js
const c = document.createElement('canvas');
document.body.appendChild(c);
c.style.width = '100%'; c.style.height = '100%';
const ctx = c.getContext('2d');
const cs = getComputedStyle(document.documentElement);
const rgb = (cs.getPropertyValue('--accent').trim() || '#5b5bf7').match(/[0-9a-f]{2}/gi).map((x) => parseInt(x, 16));
let w, h;
function resize() {
  const dpr = Math.min(devicePixelRatio || 1, 2);
  w = innerWidth; h = innerHeight;
  c.width = w * dpr; c.height = h * dpr;
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  ctx.fillStyle = '#0d0d12'; ctx.fillRect(0, 0, w, h);
  buildAndReset();
}
const A = -1.4, B = 1.6, CPARAM = 1.0, D = 0.7;
let traj = [], scaleX = 1, scaleY = 1, offX = 0, offY = 0, drawn = 0;
function buildAndReset() {
  let x = 0.1, y = 0.1;
  const N = 42000;
  traj = new Float32Array(N * 2);
  let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
  for (let i = 0; i < N; i++) {
    const nx = Math.sin(A * y) + CPARAM * Math.cos(A * x);
    const ny = Math.sin(B * x) + D * Math.cos(B * y);
    x = nx; y = ny;
    traj[i * 2] = x; traj[i * 2 + 1] = y;
    if (x < minX) minX = x; if (x > maxX) maxX = x; if (y < minY) minY = y; if (y > maxY) maxY = y;
  }
  scaleX = (w * 0.86) / (maxX - minX); scaleY = (h * 0.86) / (maxY - minY);
  const s = Math.min(scaleX, scaleY);
  offX = w / 2 - ((minX + maxX) / 2) * s; offY = h / 2 - ((minY + maxY) / 2) * s;
  scaleX = scaleY = s;
  drawn = 0;
  ctx.fillStyle = '#0d0d12'; ctx.fillRect(0, 0, w, h);
}
addEventListener('resize', resize);
resize();
function drawBatch() {
  ctx.fillStyle = 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',0.05)';
  const total = traj.length / 2, batch = 900;
  const end = Math.min(total, drawn + batch);
  for (let i = drawn; i < end; i++) {
    ctx.fillRect(traj[i * 2] * scaleX + offX, traj[i * 2 + 1] * scaleY + offY, 1.3, 1.3);
  }
  drawn = end;
}
for (let i = 0; i < 30; i++) drawBatch(); // 스크린샷 시점에 상당 부분이 이미 드러나도록
(function loop() {
  if (drawn >= traj.length / 2) { if (Math.random() < 0.004) buildAndReset(); }
  else drawBatch();
  requestAnimationFrame(loop);
})();

점 하나의 다음 위치를 이전 위치만으로 계산하는 아주 짧은 수식이 있습니다(이 데모는 Clifford Pickover가 소개한 클리포드 어트랙터를 씁니다). 같은 점에서 시작해도 초기값을 아주 살짝만 바꾸면 시간이 지날수록 완전히 다른 경로로 갈라지는데, 이게 바로 카오스의 "초기 조건 민감성"입니다. 그런데 이 궤적들은 아무 데나 흩어지지 않고 항상 특정한 나비・고리 모양의 영역 안에 머무릅니다 — 그 영역을 어트랙터(끌개)라고 부릅니다.

한 점의 경로만 보면 무질서해 보이지만, 같은 수식을 수만 번 반복해 지나간 모든 점을 아주 옅은 밝기로 겹쳐 찍으면 점이 자주 지나간 자리일수록 밝게 드러나면서 놀랍도록 정교한 구조가 떠오릅니다. 이 데모는 그 과정을 한 번에 그리지 않고 점을 순서대로 조금씩 찍어나가는 애니메이션으로 보여줍니다.

포스터·앨범 커버의 유기적인 그래픽, "수학적으로 아름다운" 배경 패턴을 만들 때 씁니다. 수식의 계수를 아주 조금만 바꿔도 전혀 다른 모양의 어트랙터가 나오므로, 여러 계수를 시도해 보며 마음에 드는 형태를 찾는 방식으로 씁니다.

언제 쓰나

앨범 커버·포스터의 추상적인 그래픽 요소, 과학·수학을 주제로 한 배경에. 계수를 몇 개 바꿔보며 마음에 드는 형태를 찾으세요.