3D Spherical Gallery
A draggable 3D room of image cards wrapped around the viewer — hover to bring a card forward, click to follow its link. Fully configurable, no assets required.
3.3k
1.3k copies
Image preview

About this component
3D Spherical Gallery places your images on the inside of a sphere and puts the
viewer at its centre. Dragging looks around the room with real momentum; the
horizontal axis loops forever while the vertical axis is rubber-banded to a
limit you set. Cards fade toward black as they move away from the centre of
view, so the composition always reads as one focused wall rather than a busy
sphere.
Cards are laid out on an exact grid — every row is a straight horizontal line
and the columns line up vertically. From there you can dial in as much
irregularity as you want: stagger alternate rows, leave random holes, vary the
size, depth and angle of each card, or add a slight tilt. Spacing works in
either direction: set the card size and let the gaps fall out, or type the gaps
you want and let the component solve for the card size.
Drop your own images in and each card can carry a link, opening in the same tab
or a new one, or fire a Framer interaction instead. A click is told apart from a
drag by distance, duration and whether the press landed and released on the same
card, so a flick that starts on a card just spins the room.
With no images set, the component draws generated "site screenshot" placeholders
from a seeded random source — so it looks finished the moment it lands on the
canvas, and stays identical between reloads until you change the seed.
Built on Three.js with no other dependencies. It rebuilds only when structural
props change; colour, motion and hover values are read live each frame, so those
sliders retune instantly. Frames are skipped when nothing is moving, animation
pauses on the Framer canvas, and everything is disposed on unmount.
Key features
Drag to explore — infinite horizontal rotation with momentum and glide;
vertical travel is rubber-banded to a configurable tilt limit
Separate drag and coast smoothing — a tight, attached feel while dragging
and a soft settle after releaseHover focus — the card under the cursor grows, steps toward the viewer,
brightens and gains a halo while everything else dims backClick-through links — per-card URL, same tab or new tab, plus an
onCardTapevent handler for Framer interactionsClick vs drag detection — distance, duration and same-card checks, so
dragging from a card never triggers navigationPress feedback — the card dips slightly while held
Two spacing modes — set the card size and read off the gaps, or set the
gaps and let the card size be solved for (honoured at the tightest row)Exact grid or scattered — stagger, fill density, size, depth, angle and
tilt variation, all from zero to as loose as you likeDepth falloff — distance fog plus an angular fade curve with adjustable
start, end, curve and floorCover or contain — images cover-cropped via UV transform, or the card
reshaped to the image's own ratioGenerated placeholders — six procedural site-screenshot layouts, twelve
palettes, editable name and headline lists, all seeded and reproducibleCursor parallax — a subtle lead toward the pointer that eases away on press
Auto drift — idle rotation with direction, speed and delay, pausing on hover
Full styling control — background, fog colour, glow colour, vignette
colour and size, corner radius, edge lightCentre overlay — title, font, colour, caption, tracking, offset and backdrop
Performance minded — idle frames skipped, DPR cap, optional antialias,
paused on the Framer canvas, full WebGL disposal on unmountResponsive — sizes to its frame via ResizeObserver, any width and height
Touch ready — pointer events throughout, no hover state stuck on mobile
No CORS pitfalls — images are never drawn to a canvas, so cross-origin
sources work
API reference
All props are optional — every value falls back to its default, and partial
objects are merged, so setting one field of a group leaves the rest intact.
Content
Prop | Type | Default | Description |
|---|---|---|---|
| Array of |
| Cards to show. |
|
|
| Cover crops to the card ratio via UV transform; contain reshapes the card to the image. |
| number (1–9999) |
| Seeds all randomness — placeholder art, shuffles, jitter, holes. |
| EventHandler | — | Fires on a card click with the card's index. |
grid
Prop | Type | Default | Range | Description |
|---|---|---|---|---|
| number |
| 1–16 | Horizontal rows of cards. |
| number |
| 3–40 | Cards per row; also sets column alignment. |
| boolean |
| — |
|
| number |
| 0.5–14 | Card width in world units. Used when |
| number |
| 0–14 | Horizontal gap, honoured at the tightest row. |
| number |
| 0–14 | Vertical gap between rows. |
| number |
| 0.3–3.5 | Card width ÷ height. |
| number |
| 0–0.5 | Fraction of the card's short edge. |
| number |
| 0–1 | Brightness of the rim highlight around each card. |
| number |
| 6–70 | Sphere radius — how far the cards sit from the viewer. |
| number |
| 0.02–0.5 | Top row's latitude, × π from the pole. |
| number |
| 0.5–0.98 | Bottom row's latitude. |
| number |
| 0–1 | Offsets alternate rows by up to half a slot. |
| number |
| 0.2–1 | Chance a slot is filled; below 1 leaves holes. |
| number |
| 0–0.6 | Per-card random size spread. |
| number |
| 0–6 | Per-card radial offset, in world units. |
| number |
| 0–0.6 | Per-card offset from its exact grid slot. |
| number |
| 0–0.3 | Per-card random roll, in radians. |
lens
Prop | Type | Default | Range | Description |
|---|---|---|---|---|
| number |
| 25–115 | Camera FOV in degrees. |
| number |
| 1–3 | Caps device pixel ratio. |
| boolean |
| — | WebGL MSAA. |
look
Prop | Type | Default | Range | Description |
|---|---|---|---|---|
| color |
| — | Behind the WebGL canvas. |
| color |
| — | Colour cards fade toward with distance. |
| number |
| 0–0.08 | Exponential fog density. |
| number |
| 0–0.8 | Halo strength behind each card. |
| color |
| — | Halo tint. |
| number |
| 0–1 | Facing value where a card is fully lit. |
| number |
| 0–1 | Facing value where it has faded out. |
| number |
| 0.3–4 | Exponent on the falloff; higher is more contrasty. |
| number |
| 0–0.5 | Brightness floor for the darkest cards. |
| number |
| 0–1 | Vignette opacity. |
| color |
| — | Vignette colour. |
| number |
| 60–200 | Vignette spread, in percent. |
motion
Prop | Type | Default | Range | Description |
|---|---|---|---|---|
| boolean |
| — | Enables pointer dragging. |
| number |
| 0.0005–0.012 | Radians per pixel dragged. |
| boolean |
| — | Reverses drag direction. |
| boolean |
| — | Horizontal-only dragging. |
| boolean |
| — | Enables wheel and trackpad rotation. |
| number |
| 0–0.01 | Radians per wheel unit. |
| number |
| 0.75–0.995 | Momentum decay after release; higher glides longer. |
| number |
| 0.02–0.5 | Easing while coasting. |
| number |
| 0.05–1 | Easing while dragging; higher tracks the pointer more tightly. |
| number |
| 0–1.2 | Max up/down tilt, in radians. |
| number |
| 0–1 | Resistance when dragged past the tilt limit. |
| number |
| 0–0.3 | How far the rubber band may visibly stretch, in radians. |
| number |
| 0–3 | Idle rotation speed; |
|
|
| — | Idle rotation direction. |
| number |
| 0–6 | Seconds of stillness before drift starts. |
| number |
| 0–0.12 | Lead toward the cursor, in radians. |
| number |
| −180–180 | Initial horizontal rotation, in degrees. |
| number |
| −40–40 | Initial vertical tilt, in degrees. |
hover
Prop | Type | Default | Range | Description |
|---|---|---|---|---|
| boolean |
| — | Mouse only; touch has no hover state. |
| number |
| 0–0.8 | How much the card grows. |
| number |
| 0–0.3 | Step toward the viewer, as a fraction of distance. |
| number |
| 0–2 | Extra brightness on the hovered card. |
| number |
| 0–10 | Halo multiplier on the hovered card. |
| number |
| 0–0.9 | How far every other card drops back. |
| number |
| 0.03–0.6 | Hover in/out easing. |
| boolean |
| — | Holds auto-drift still while hovering. |
| boolean |
| — | Grab / grabbing / pointer cursors. |
click
Prop | Type | Default | Range | Description |
|---|---|---|---|---|
| boolean |
| — | Enables card links and |
| number |
| 0–0.3 | How far the card dips while held. |
| number |
| 0–40 | Pixels of movement still counted as a click. |
| number |
| 150–2000 | Milliseconds above which a press is a hold, not a click. |
overlay
Prop | Type | Default | Range | Description |
|---|---|---|---|---|
| boolean |
| — | Shows the centre wordmark. |
| string |
| — | Newlines become line breaks. |
| font | Georgia 64 / 1.05em | — | Extended font control. |
| color |
| — | Title colour. |
| number |
| 0–1 | Shadow strength behind the title. |
| string |
| — | Caption under the title. |
| color |
| — | Caption colour. |
| number |
| 6–32 | Caption size in pixels. |
| number |
| 0–12 | Caption letter spacing. |
| boolean |
| — | Uppercases the caption. |
| number |
| 0–80 | Space between title and caption. |
| number |
| −400–400 | Vertical offset of the whole overlay. |
| number |
| 0–1 | Dark pool behind the overlay for legibility. |
placeholder
Used only while images is empty.
Prop | Type | Default | Range | Description |
|---|---|---|---|---|
| number |
| 0–1 | Share of light versus dark palettes. |
| number |
| 0–1 | Chance a card gets a browser title bar. |
| string | 27 names | — | One per line; used for card headings. |
| string | 14 lines | — | One per line; used for editorial cards. |
Notes
World units.
cardWidth,gapX,gapY,depthVariationanddistance
share one scale. Raisingdistancewidens gaps at a fixed card size.Rebuild vs live.
images,imageFit,seed,grid,placeholder,lens.fieldOfViewandlens.antialiasrebuild the scene.look,motion,hover,clickandoverlayare read every frame and apply instantly.Dependency. Three.js r160, imported from
https://esm.sh/three@0.160.1.
Swap that line forimport * as THREE from "three"if your project resolves
npm packages directly.Canvas behaviour. On the Framer canvas, auto-drift, hover and navigation
are suppressed; all three run in Preview and on the published site.
Details
Category
Gallery
Media
Image
Views
3.3k
Copies
1.3k
Paste directly onto your Framer canvas.
