---
title: SC Golden Spiral
description: Golden-angle spiral of SVG dots with optional pulses and rotation.
url: https://secretocho.design/lab/sc-golden-spiral/
type: SoftwareSourceCode
status: working
published: 2025-08-26
updated: 2025-08-26
---

# SC Golden Spiral

> Golden-angle spiral of SVG dots with optional pulses and rotation.

component 14 / 28 · WORKING

- **type**: Code Component
- **platform**: Framer
- **last update**: 2025-08-26
- **read time**: 6–8 min

![A still of the SC Golden Spiral demo, as its module draws it with reduced motion.](https://secretocho.design/_astro/still.C5QR5KXU_Zyd8vd.webp)

*fig 00 · live demo, ported from **SC\_GoldenSpiral.tsx***

Generates N points using the golden angle π(3−√5) with radius proportional to √(i/N); dots render as \<circle\> elements with optional SVG \<animate\> pulses sweeping inside→outside (or reverse) and CSS rotation on the \<svg\>.

An SVG point-field arranged along the golden-angle (Fermat) spiral. Each dot can pulse in size and opacity with phase offsets from the spiral index, and the entire field can rotate smoothly. Works great for meditative backgrounds, hero motifs, and data-art accents.

- Visual
- SVG
- Generative Math

## Main

### Overview

- **Built With**: React, SVG, CSS, Framer Code Component API
- **Layout Support**: Fully Responsive or fixed width/height
- **Orientation**: Full Fill motif
- **Ideal Use Case**: Ambient hero visuals, decorative backgrounds, brand motion textures

### Tags

- golden-angle
- spiral
- generative
- svg
- pulse
- animation
- rotate
- responsive

### Code comment

```tsx
/**
 * SC Golden Spiral
 * © SecretoCho Design 2025
 * Golden-angle point layout with optional per-dot pulse and global rotation.
 * @framerDisableUnlink
 * @framerSupportedLayoutWidth any
 * @framerSupportedLayoutHeight any
 */
```

### Dependencies

- **Technologies**: None (pure SVG/React)
- **Notes**: No external libs; uses native SVG <animate> for per-dot motion.

### Complexity

- **Logic Level**: Low–Medium (deterministic geometry + simple animation)
- **Runtime Cost**: Low–Medium (hundreds of SVG circles + optional anim)
- **Component Size**: ~2–3 KB (raw TSX)
- **Notes**: showFPS is debug-only; disable for production.

## Guide

### Instructions

1. Add **SCGoldenSpiral** to your canvas; choose **Size Mode** = fixed (px) or dynamic (% of container).
2. Set **Points** (e.g., 400–1200) and **Dot Radius** (1.5–3 for dense fields).
3. Enable **Pulse Effect** to animate dot **r** and **opacity**; choose **Duration**, **Min/Max Size**, **Min/Max Opacity**, and **Pulse Direction** (inside or outside).
4. Toggle **Rotate** for slow turntable motion; adjust **Rotation Speed** and **Direction**.
5. Frame the motif via **Anchor** presets plus **X/Y Offset**.

### Examples / Presets

- Calm Aura
  
  points=700 · r=2 · pulseEffect=on · duration=4 · size 0.8–1.25 · opacity 0.25–0.9 · rotate off
  
- Hero Drift
  
  points=900 · r=2 · pulseEffect=on · duration=3 · rotate on · speed=0.2 · dir=clockwise
  
- Minimal Static
  
  points=500 · r=1.5 · pulseEffect=off · rotate off
  

## Mechanics

### How it Works

- **Golden-angle placement**: For index i (0-based), uses idx=i+0.5, frac=idx/N, r=√(frac)\*maxRadius, θ=idx\*φ, φ=π(3−√5).
- **Responsive sizing**: maxRadius derives from the smaller of width/height; in dynamic mode it scales via **Width%/Height%** of the container.
- **Pulsing**: Each circle animates r and opacity with SVG \<animate\>, offset by its normalized frac. Direction flips phase (inside uses 1−frac).
- **Rotation**: A requestAnimationFrame loop increments a local rotation state; applied as transform: rotate(...) on the \<svg\>.
- **Anchoring**: Predefined anchors shift the cluster by ±¼ of the shorter side; **X/Y Offset** fine-tunes.

### Performance & Tuning

- SVG handles hundreds of circles well; thousands plus pulsing is still reasonable on desktops.
- Prefer points ≤ 1200 on laptops; reduce **dotRadius** for density instead of adding excessive points.
- Keep **duration ≥ 2s** for smoother, less battery-intense motion.
- Disable **showFPS** when shipping.

### Compatibility & Limits

- Evergreen browsers support SVG animation broadly; older iOS Safari may need testing for heavy \<animate\> counts.
- Rotation uses CSS transforms—GPU-friendly.
- No SSR output differences; geometry is computed at mount with current box size.

## Quality

### Accessibility

- Decorative by default; add aria-hidden="true" if it conveys no information.
- If used behind text, ensure adequate contrast and avoid excessive motion that could distract.

### Security & Privacy

- No network, storage, or permissions.
- Only window resize listeners; they’re removed on unmount.
- No dangerouslySetInnerHTML or dynamic code execution.

## Reference

### Props

| name | type | default | description |
| --- | --- | --- | --- |
| points | number | 600 | Number of dots in the spiral |
| dotRadius | number | 2 | Base circle radius (px) |
| duration | number | 3 | Pulse cycle duration (seconds) |
| fillColor | string | #ffffff | Dot fill color |
| pulseEffect | boolean | true | Enable SVG pulse animation |
| opacityMin | number | 0.3 | Minimum opacity during pulse (0–1) |
| opacityMax | number | 1 | Maximum opacity during pulse (0–1) |
| sizeMin | number | 0.5 | Radius multiplier at pulse minimum |
| sizeMax | number | 1.5 | Radius multiplier at pulse peak |
| pulseDirection | enum | outside | Wave phase origin (inside/outside) |
| sizeMode | enum | fixed | Spiral bounds mode (fixed px or dynamic %) |
| ellipseWidth | number | 200 | Horizontal bound in px (fixed mode) |
| ellipseHeight | number | 600 | Vertical bound in px (fixed mode) |
| widthPercent | number | 12 | Horizontal bound as % of container (dynamic) |
| heightPercent | number | 48 | Vertical bound as % of container (dynamic) |
| positionAnchor | enum | center | Anchor for the spiral (center/top/bottom/left/right/corners) |
| xOffset | number | 0 | Additional X translation (px) |
| yOffset | number | 0 | Additional Y translation (px) |
| showFPS | boolean | false | Show live FPS counter (debug only) |
| rotate | boolean | false | Rotate the entire spiral group |
| rotationDirection | enum | counter-clockwise | Rotation direction |
| rotationSpeed | number | 0.2 | Angular step in degrees per animation frame |

### Notes & Tips

- To bias density inward or outward, adjust **dotRadius** and **points** together; the √r distribution already spreads points evenly.
- For crisp aesthetics, keep **fillColor** opaque and modulate visibility via **opacityMin/Max** only.

### Troubleshooting / FAQ

Looks off-center

Check **Anchor** + **X/Y Offset**; remember anchor shifts by ¼ of the shorter side.

Too busy/stuttery

Lower **points**, raise **duration**, or disable **rotate**.

Pulses feel chaotic

Reduce **sizeMax** and narrow **opacity** range (e.g., 0.35–0.8).

## Source

### Header comment

*the CMS Code-Comment · SC\_GoldenSpiral.tsx has no doc comment*

```tsx
/**
 * SC Golden Spiral
 * © SecretoCho Design 2025
 * Golden-angle point layout with optional per-dot pulse and global rotation.
 * @framerDisableUnlink
 * @framerSupportedLayoutWidth any
 * @framerSupportedLayoutHeight any
 */
```

[props \[REF\]](#reference)

### Key excerpt

The golden angle π(3−√5) and a radius of √(i/N): every point of the spiral is placed in this loop.

*SC\_GoldenSpiral.tsx · lines 13–27 · tsx*

```tsx
const GOLDEN_ANGLE = Math.PI * (3 - Math.sqrt(5))

function generateSpiralPoints(N: number, maxRadius: number) {
    const points = []
    for (let i = 0; i < N; i++) {
        const idx = i + 0.5
        const frac = idx / N
        const r = Math.sqrt(frac) * maxRadius
        const theta = idx * GOLDEN_ANGLE
        const x = r * Math.cos(theta)
        const y = r * Math.sin(theta)
        points.push({ x, y, frac })
    }
    return points
}
```

## Credits

### Credits

- **Original animation:** *Filip Zrnzević* — golden-angle (Fermat) spiral of SVG circles with phased \<animate\> pulses for radius and opacity.
- **Framer/React adaptation:** *SecretoCho Design* — responsive sizing (fixed/dynamic), anchor presets + X/Y offsets, global rotation, inside/outside pulse direction, property controls, and optional FPS overlay.
- **Derivative work notice:** This component is an adaptation of Filip Zrnzević’s original concept. Before commercial use or redistribution, review the original work’s license/terms and ensure proper attribution consistent with those terms.

- **inspired by**: Filip Zrnzevic · codepen.io/filipz/pen/KwwKjxq

SecretoCho Design 2025

### Disclaimer

- **Derivative work notice:** This component is an adaptation of Filip Zrnzević’s original concept. Before commercial use or redistribution, review the original work’s license/terms and ensure proper attribution consistent with those terms.
- **Warranty:** Provided “as is” for visual/UX purposes only. Validate performance, accessibility (motion/contrast), and compatibility in your target environments.

## Proves

- [Creative coding](https://secretocho.design/about/#capabilities)

## Hiring a design engineer?

I’m open to senior design engineer roles: remote from Belgrade, or relocation with visa sponsorship. Write to me, or read the CV first. Client work stays selective, one project at a time.

[sc@secretocho.design](mailto:sc@secretocho.design)

[read the CV](https://secretocho.design/cv/) · [LinkedIn](https://www.linkedin.com/in/secretocho/)
