Code

SVG

Generative Art

Expert Real-time animated generative art using raw SVG DOM — Lissajous orbital figures and golden-angle phyllotaxis spiral rendered with requestAnimationFrame and document.createElementNS. MDN createElementNS

New random palette & seed
// Angular component (AfterViewInit + NgZone)
private ns = 'http://www.w3.org/2000/svg';
private raf = 0;
private frame = 0;

ngAfterViewInit() {
  if (!isPlatformBrowser(this.platformId)) return;
  this.init();
}

private init() {
  const svg = document.createElementNS(this.ns, 'svg');
  svg.setAttribute('viewBox', '0 0 480 300');
  svg.style.background = '#0f172a';

  this.rootG = document.createElementNS(this.ns, 'g');
  svg.appendChild(this.rootG);
  this.containerRef.nativeElement.appendChild(svg);

  this.zone.runOutsideAngular(() => this.animate());
}

private animate() {
  const t = this.frame++;
  const cx = 240, cy = 150;

  for (let i = 0; i < 5; i++) {
    // Lissajous orbital trail
    const freqA = 2 + (i % 3);
    const freqB = 3 + (i % 2);
    const r = 40 + i * 18;
    const tNorm = t * 0.012 + i * 1.3;
    const x = cx + Math.cos(freqA * tNorm) * r;
    const y = cy + Math.sin(freqB * tNorm) * r;

    // Phyllotaxis golden-angle dot
    // 137.508° = golden angle
    const phi = (t * 0.03 + i * 137.508
                 * (Math.PI / 180)) % (Math.PI * 2);
    const pr  = Math.sqrt(t * 0.04 + i * 5) * 4;

    this.addDot(x, y, this.palette[i % 5]);
  }

  // DOM pruning — prevent memory growth
  if (this.rootG.childNodes.length > 20000) {
    for (let k = 0; k < 3000; k++)
      this.rootG.removeChild(this.rootG.firstChild!);
  }

  this.raf = requestAnimationFrame(() => this.animate());
}

private addDot(x: number, y: number, fill: string) {
  const c = document.createElementNS(this.ns, 'circle');
  c.setAttribute('cx', String(x));
  c.setAttribute('cy', String(y));
  c.setAttribute('r',  '1.4');
  c.setAttribute('fill', fill);
  this.rootG.appendChild(c);
}
Key Concepts
  • document.createElementNS('http://www.w3.org/2000/svg', 'circle') — creates SVG elements in the SVG namespace
  • Lissajous figures — parametric curves x = A·cos(aθ), y = B·sin(bθ); different frequency ratios produce different orbit shapes
  • Phyllotaxis golden angle — 137.508° between successive elements produces the sunflower spiral pattern found in nature
  • NgZone.runOutsideAngular() — keeps the rAF loop outside Angular's change-detection zone for performance
  • DOM pruning — when child count exceeds a threshold (20 000), remove the oldest nodes to bound memory use
  • requestAnimationFrame — synchronises drawing with the browser's repaint cycle (~60 fps)
  • cancelAnimationFrame(this.raf) in ngOnDestroy() — essential to stop the loop when the component is destroyed