SecretoCho
menu

component 02 / 28WORKINGfeatured

SC Animated Radial Ellipse

type
Code Component
platform
Framer
last update
read time
7–9 min
license
SecretoCho Design
needs JavaScript

demo · runs with JavaScript

fig 00 · live demo, ported from SC_AnimatedRadialEllipse.tsx · starts on Loader Minimal, since the source default is still

Renders a radial array of SVG <ellipse> strokes with optional gradient, rotation, and trim-path windows; dimensions adapt via fixed or container-relative radii.

A highly customizable SVG animation that draws multiple rotating ellipses in radial symmetry. Supports trim-path style reveals, gradient strokes, and responsive sizing—perfect for abstract loaders, hypnotic loops, animated backgrounds, and generative motifs.

  • Pro Tips
  • Generative

Main

Overview

Built With
React, SVG, CSS, Framer Code Component API
Layout Support
Fully Responsive or fixed width/height
Orientation
Full Fill or Text Mask
Ideal Use Case
Animated backgrounds, design motifs, abstract loaders

Tags

  • svg
  • ellipse
  • animation
  • radial
  • trim
  • stroke-dash
  • gradient
  • responsive
  • generative

Code comment

/** * SC Animated Radial Ellipse * © SecretoCho Design 2025 (https://secretocho.design) * Dynamic SVG-based radial ellipse pattern with customizable count, size, and animation. * Ideal for hero visuals, interactive backgrounds, and meditative art pieces. * @framerDisableUnlink * @framerSupportedLayoutWidth any * @framerSupportedLayoutHeight any */

Dependencies

Technologies
None (pure SVG/React)
Notes
No runtime libraries required; works with Framer’s standard runtime.

Complexity

Logic Level
Medium (animated render, dash math)
Runtime Cost
Medium–High with rotate + trim active (bounded by ellipse count)
Component Size
~3–4 KB (raw TSX)
Notes
Use Show FPS only while debugging.

Guide

Instructions

  1. Add SCAnimatedRadialEllipse to your canvas.
  2. Choose sizing: Size Mode = fixed (px) or dynamic (% of container).
  3. Set geometry: Count, Width/Height (or Width%/Height%), Width/Height Ratio.
  4. Style strokes: Stroke Width/Color or enable Gradient Blend and set a unique Gradient ID.
  5. Animate: toggle Animate → set Rotation direction/speed.
  6. Trim window (optional): enable Trim Path, tune Trim Speed, Trim Offset, Trim Phase Start, and Mirror Trim.
  7. Position: set Anchor and X/Y Offset.
  8. (Debug) Toggle Show FPS during tuning; disable before publish.

Examples / Presets

  • Loader Minimal

    count
    9
    strokeWidth
    1
    animate
    on
    trimPath
    on
    trimSpeed
    0.006
    rotationSpeed
    0.15
    gradient
    off
  • Hypnotic Halo

    count
    33
    strokeWidth
    2
    gradient
    on
    ellipseRatioX
    1
    ellipseRatioY
    1.2
    animate
    on
    trimPath
    on
    mirrorTrim
    on
  • Low-Power Accent

    count
    13
    animate
    on
    trimPath
    off
    rotationSpeed
    0.1
    strokeWidth
    1

Mechanics

How it Works

  • Odd symmetry: Ensures an odd Count for balanced radial spacing (angleStep = 360/oddCount).
  • Sizing: Uses fixed px or container-relative % to compute actualWidth/Height; ratios (ellipseRatioX/Y) thin/flatten radii (rx = width/ratioX, ry = height/ratioY).
  • Rotation: Each ellipse receives a per-element transform: rotate(angle, cx, cy) where angle = index*step + rotation.
  • Trim window: Approximates ellipse perimeter with Ramanujan’s formula; applies strokeDasharray=perimeter and animates strokeDashoffset by a sinusoidal phase (supports Mirror Trim by offsetting half-perimeter).
  • Gradient: Optional <linearGradient id={gradientId}> stroked via url(#id)—unique IDs prevent collisions across instances.
  • Layout: ResizeObserver and a resize handler update container dimensions; anchor presets offset the cluster by quarter-frame steps plus X/Y offsets.

Performance & Tuning

  • Cost scales with Count × Stroke effects. Keep strokeWidth ≤ 2–3px when Trim Path is on.
  • Prefer moderate Count (7–33 UI accents, 33–99 hero visuals).
  • Large gradients across many ellipses are expensive—reuse one gradient where possible.
  • Disable Show FPS for production.

Compatibility & Limits

  • Modern evergreen browsers (Chrome/Edge/Safari/Firefox).
  • SVG gradients and stroke-dash animations are broadly supported; verify on older mobile Safari if using heavy gradients.
  • Multiple instances on one page must use unique Gradient ID.

Quality

Accessibility

  • Decorative by default; if it conveys no information, wrap with aria-hidden="true".
  • In Text Mask scenarios (external), ensure readable contrast or provide a plain-text alternative nearby.

Security & Privacy

  • No network calls; no data stored.
  • Typed props; no dangerouslySetInnerHTML / eval.
  • No device permissions.
  • Cleanup note: event listeners created for resize are removed; ResizeObserver is disconnected on unmount.

Reference

Props

nametypedefaultdescription
countnumber15Number of ellipses (auto-forces odd for symmetry)
strokeWidthnumber1SVG stroke width of each ellipse (px)
strokeColorstring#FF4081Stroke color (used if Gradient Blend is off)
gradientbooleanfalseEnable linear gradient stroke instead of solid color
gradientIdstringgrad-defaultUnique SVG gradient id (avoid collisions)
sizeModestring(enum)fixedEllipse sizing mode (fixed or container-relative)
ellipseWidthnumber200Ellipse width in pixels (when Size Mode = fixed)
ellipseHeightnumber600Ellipse height in pixels (when Size Mode = fixed)
widthPercentnumber12Ellipse width as % of container (when Size Mode = dynamic)
heightPercentnumber48Ellipse height as % of container (when Size Mode = dynamic)
ellipseRatioXnumber1Width divisor for ellipse radius (higher = thinner)
ellipseRatioYnumber1Height divisor for ellipse radius (higher = flatter)
animatebooleanfalseTurn on rotation/trim animation loop
showFPSbooleanfalseOverlay a live FPS counter (for testing)
rotationDirectionstring(enum)counter-clockwiseRotation direction (counter-clockwise/clockwise)
rotationSpeednumber0.2Degrees per frame tick while animating
trimPathbooleanfalseAnimate a traveling stroke “window” via dash offsets
mirrorTrimbooleanfalseMirror trim window around the ellipse path
trimSpeednumber0.01Trim phase speed (cycles per frame tick)
trimOffsetnumber0Per-ellipse trim phase offset (−1..1)
trimStartOffsetnumber0Global trim phase start (0..1)
positionAnchorstring(enum)centerBase anchor for the ellipse cluster
xOffsetnumber0Horizontal offset from anchor (px)
yOffsetnumber0Vertical offset from anchor (px)

Notes & Tips

  • If gradients look “shared” between instances, duplicate and change Gradient ID.
  • Uneven trim? Keep trimSpeed small and confirm dash length uses the current perimeter (already computed).
  • For ultra-smooth rotation, prefer modest rotationSpeed (0.1–0.3).

Troubleshooting / FAQ

Gradient ID collision

Set a unique gradientId per component instance.

Stuttering

Lower count, reduce strokeWidth, and disable mirrorTrim.

Trim not visible

Ensure Trim Path is on; try increasing strokeWidth or lowering trimSpeed.

Source

Header comment

SC_AnimatedRadialEllipse.tsx · lines 6–14 · header comment
/** * SC Animated Radial Ellipse * * © SecretoCho Design 2025 (https://secretocho.design) * Generates a dynamic SVG-based radial ellipse pattern with customizable count, size, and animation behaviors. * Ideal for hero visuals, interactive backgrounds, or meditative animated art pieces. * @framerDisableUnlink * @framerSupportedLayoutWidth any * @framerSupportedLayoutHeight any */

props [REF]

Key excerpt

The ellipse loop: Ramanujan’s approximation gives each ellipse’s length, a sine phase slides its dash window along it, and each copy turns by one angle step.

SC_AnimatedRadialEllipse.tsx · lines 155–189 · tsx
    const ellipses = []    for (let i = 0; i < oddCount; i++) {        const angle = i * angleStep + rotation        const rx = actualWidth / ellipseRatioX        const ry = actualHeight / ellipseRatioY        const length =            Math.PI * (3 * (rx + ry) - Math.sqrt((3 * rx + ry) * (rx + 3 * ry)))        const t = Math.sin(            (trimPhase + i * trimOffset + trimStartOffset) * 2 * Math.PI        )        const normalized = (t + 1) / 2        const offset = trimPath ? normalized * length : 0        const dasharray = trimPath ? `${length}` : undefined        const dashoffset = trimPath            ? mirrorTrim                ? `${offset - length / 2}`                : `${offset}`            : undefined        ellipses.push(            <ellipse                key={i}                cx={centerX + offsetX}                cy={centerY + offsetY}                rx={rx}                ry={ry}                stroke={gradient ? `url(#${gradientId})` : strokeColor}                strokeWidth={strokeWidth}                fill="none"                strokeDasharray={dasharray}                strokeDashoffset={dashoffset}                transform={`rotate(${angle}, ${centerX + offsetX}, ${centerY + offsetY})`}            />        )    }

Credits

Credits

Concept, implementation, and Framer adaptation by SecretoCho Design.
Ellipse trim math uses a Ramanujan-style circumference approximation.

license
SecretoCho Design

SecretoCho Design 2025

Disclaimer

Proves

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

read the CV · LinkedIn