Image sphere
A cloud of photos on an invisible sphere that drifts, spins on a drag and opens one on a click.
Photos of landscapes, animals and fruit floating on an invisible sphere, nearer ones larger.npx skills add https://design.how/vault/image-sphereInstalls the template, the brief and a check script as one skill.
What it is
Seventeen photos float in a loose ball in the middle of the card, fjords, waterfalls, mountains, a deer, a walrus, strawberries, a bird in flight. Each one is a flat picture that always turns to face the viewer, so the sphere is never drawn; it shows up only as the arrangement, with the near photos bigger and in front and the far ones small behind them. The whole cloud turns slowly on two axes at once, so it never settles into one plain spin.
Each photo is a three.js plane, 50 units tall and as wide as its aspect, placed at a seeded random point on a sphere of radius 180 with the radius jittered by up to 40 either way. Every frame the planes get the inverse of the group's rotation, which keeps them square to the camera, and a scale of 0.8 plus their world depth over 2000, eased, so depth reads as size. Transparent planes do not write depth, so overlaps blend cleanly.
A drag adds to a target rotation that the sphere eases toward at 0.2 a frame; on release the last step becomes a spin that decays by 0.94 a frame and hands back to the drift. A press that moves less than 6 pixels is a click. It ray-casts the front-most photo and eases it to a point 300 units in front of the camera, scaled to fill 62% of the view height there, while every other photo fades to 16% opacity. Hovering a photo grows it to 120%.
How it works
- Make one plane per photo with a basic material, depthWrite off, and place it at a seeded random point on a sphere with a jittered radius.
- Each frame, add a small constant drift to the group rotation plus the eased drag rotation, and copy the inverse group quaternion onto every plane so it faces the camera.
- Scale each plane by 0.8 + worldZ / 2000, times the hover scale when the ray cast hits it, eased toward that target.
- Turn the last drag step into a velocity on release and decay it each frame, so a flick keeps spinning.
- On a click, ease the hit plane from its home spot to a fixed point in front of the camera, converted into group space, and dim the others.
- Stop on webglcontextlost, and on destroy dispose every geometry, texture and material, then renderer.dispose() and renderer.forceContextLoss().
- Under reduced motion, snap every plane to its billboard and depth scale and draw once; clicking does nothing.
What you can change
SPHERE_PATHS(seventeen photos): The images. Any count works.RADIUS(180): The sphere the photos sit on.PLANE_SIZE(50): The height of a photo plane before depth scaling.AUTO_ROT_Y(0.0005): The ambient drift per frame around the vertical axis.HOVER_SCALE(1.2): How much the photo under the pointer grows.INERTIA_DECAY(0.94): How fast a flick spin dies away.FOCUS_FILL(0.62): How much of the view height a clicked photo fills.