Dolly Zoom

The vertigo shot, a corridor with a red door stretches deeper while the subject in the middle keeps its exact size

Installation
$ pnpm dlx shadcn@latest add @remocn/dolly-zoom

Usage

DollyZoom renders a perspective corridor with a red door at the far end and a standing figure in the middle. Over the move the camera dollies toward the figure while the focal length shortens at exactly the same rate, so the figure never changes size while the corridor stretches away behind it, the way the shot works in film. Floor tiles, ceiling lights and frame lines fade with distance, and a vignette darkens the corners.

tsx
import { DollyZoom } from "@/components/remocn/dolly-zoom";
 
export const Vertigo = () => <DollyZoom />;

intensity sets how far the camera travels, from 0 (no move) to 2. At 1 the camera ends at about 37% of its starting distance. reverse plays the same move backward: the corridor starts stretched and compresses toward the subject.

Your own subject

Children replace the figure. They are centered in the frame and are not scaled, which is what keeps them steady.

tsx
import { Img, staticFile } from "remotion";
import { DollyZoom } from "@/components/remocn/dolly-zoom";
 
export const LogoVertigo = () => (
  <DollyZoom intensity={1.4} doorColor="#3D7BFF">
    <Img src={staticFile("logo.svg")} style={{ height: 160 }} />
  </DollyZoom>
);

The built-in figure stands on the floor. Children sit at the frame center instead, so a tall subject may overlap the floor line; that is usually fine for a logo or a word.

Timing

At 30 fps and speed={1}:

FramesMotion
0–4The shot holds on the starting framing
4–36The camera dollies in while zooming out on one eased curve, fastest around frame 16
36+The shot holds on the stretched corridor

speed scales the move, so speed={2} ends at frame 18.

Props8

PropTypeDefault
children
ReactNode—

Subject held at a constant size in the frame center. Defaults to a standing figure

intensity
number1

How far the camera dollies in, 0 to 2

reverse
booleanfalse

Plays the move backward so the corridor compresses toward the subject

colors
Partial<DollyZoomColors>{ background: "#0B0B0B", wall: "#1B1B1B", wallAlt: "#151515", floor: "#262626", floorAlt: "#1D1D1D", line: "#FFFFFF", light: "#FFFFFF", door: "#E5322D", figure: "#FFFFFF" }

Corridor, line, ceiling light, door and figure colors; merged over the defaults. The flat color props below win over it

doorColor
string"#E5322D"

Door color; overrides colors.door

figureColor
string"#FFFFFF"

Default figure color; overrides colors.figure

lineColor
string"#FFFFFF"

Corridor edge lines; overrides colors.line

speed
number1

Playback multiplier

  • childrenReactNode

    Subject held at a constant size in the frame center. Defaults to a standing figure

  • intensitynumber

    How far the camera dollies in, 0 to 2

    Default1

  • reverseboolean

    Plays the move backward so the corridor compresses toward the subject

    Defaultfalse

  • colorsPartial<DollyZoomColors>

    Corridor, line, ceiling light, door and figure colors; merged over the defaults. The flat color props below win over it

    Default{ background: "#0B0B0B", wall: "#1B1B1B", wallAlt: "#151515", floor: "#262626", floorAlt: "#1D1D1D", line: "#FFFFFF", light: "#FFFFFF", door: "#E5322D", figure: "#FFFFFF" }

  • doorColorstring

    Door color; overrides colors.door

    Default"#E5322D"

  • figureColorstring

    Default figure color; overrides colors.figure

    Default"#FFFFFF"

  • lineColorstring

    Corridor edge lines; overrides colors.line

    Default"#FFFFFF"

  • speednumber

    Playback multiplier

    Default1