Iris Wipe

Close a cartoon iris on the subject, hold it as a dot for a beat, then open it on the next scene

Installation
$ pnpm dlx shadcn@latest add @remocn/iris-wipe

Usage

irisWipe() is a Remotion transition presentation. Pass it to a TransitionSeries.Transition between two sequences. The first half of the transition closes a circle on the outgoing scene: it rushes in from outside the frame, slows into a small dot of holdRadius, then snaps shut. Everything outside the circle is filled with color. The second half opens a circle on the incoming scene from the same center. The closing radius follows one continuous curve, so the iris never fully stops between the rush and the hold.

Both scenes render once per frame, so it is as cheap as a transition gets.

import { TransitionSeries, linearTiming } from "@remotion/transitions";
import { irisWipe } from "@/components/remocn/iris-wipe";
 
export const MyVideo = () => (
  <TransitionSeries>
    <TransitionSeries.Sequence durationInFrames={70}>
      <SceneA />
    </TransitionSeries.Sequence>
    <TransitionSeries.Transition
      timing={linearTiming({ durationInFrames: 36 })}
      presentation={irisWipe({ centerX: 0.62, centerY: 0.4 })}
    />
    <TransitionSeries.Sequence durationInFrames={70}>
      <SceneB />
    </TransitionSeries.Sequence>
  </TransitionSeries>
);

Timing

ProgressWhat happens
0 to 0.5Iris closes on the outgoing scene, lingers as a dot, snaps shut
0.5Frame is fully color
0.5 to 1Iris opens on the incoming scene from the same center

Props

irisWipe(props) accepts:

PropTypeDefaultDescription
color
string"#000000"Fill shown outside the iris while it is closed.
centerX
number0.5Horizontal iris center, 0 (left) to 1 (right).
centerY
number0.5Vertical iris center, 0 (top) to 1 (bottom).
holdRadius
number12Radius of the held dot, in CSS circle() percent of the frame (150 covers the whole frame). 0 skips the hold and closes straight down.