Custom presentations
This page describes how to create your own custom effect for <TransitionSeries>
.
Concept
A presentation is a higher order component which wraps around the entering slide as well as the exiting slide and which implements an effect based on three parameters:
The currentpresentationProgress
, influenced by the
timing of the transition
The
presentationDirection
, either entering
or exiting
The
presentationDurationInFrames
(available from v4.0.153)
4
Additional developer-defined passedProps
Boilerplate
A custom presentation is a function which returns an object of type TransitionPresentation
.
It is an object with a React component (component
) and React props which are passed to the component as passedProps
.
custom-presentation.tsxtsx
import type {TransitionPresentation } from '@remotion/transitions';typeCustomPresentationProps = {width : number;height : number;};export constcustomPresentation = (props :CustomPresentationProps ,):TransitionPresentation <CustomPresentationProps > => {return {component :StarPresentation ,props };};
custom-presentation.tsxtsx
import type {TransitionPresentation } from '@remotion/transitions';typeCustomPresentationProps = {width : number;height : number;};export constcustomPresentation = (props :CustomPresentationProps ,):TransitionPresentation <CustomPresentationProps > => {return {component :StarPresentation ,props };};
The component
is a React component which receives the following props:
children
: The markup to wrap around
presentationDirection
: Either
"entering"
or "exiting"
presentationProgress
: A number between
0
and 1
which represents the progress of the transition.
passedProps
: The custom props passed to the presentation
StarPresentation.tsxtsx
import type {TransitionPresentationComponentProps } from '@remotion/transitions';import {AbsoluteFill } from 'remotion';constStarPresentation :React .FC <TransitionPresentationComponentProps <CustomPresentationProps >> = ({children ,presentationDirection ,presentationProgress ,passedProps }) => {return (<AbsoluteFill ><AbsoluteFill >{children }</AbsoluteFill ></AbsoluteFill >);};
StarPresentation.tsxtsx
import type {TransitionPresentationComponentProps } from '@remotion/transitions';import {AbsoluteFill } from 'remotion';constStarPresentation :React .FC <TransitionPresentationComponentProps <CustomPresentationProps >> = ({children ,presentationDirection ,presentationProgress ,passedProps }) => {return (<AbsoluteFill ><AbsoluteFill >{children }</AbsoluteFill ></AbsoluteFill >);};
Example
The following example implements a star mask transition:
Based on thepassedProps
height
and width
, the inner radius of the star is calculated that will completely fill the canvas.
Using
@remotion/shapes
, an SVG path is calculated, and grown from zero to the full size of the canvas. 3
The presentationProgress
is used to interpolate the shape
size. 4
@remotion/paths
is used to center the star in the middle of the canvas.
A
clipPath
is used to clip the entering slide.
Inside the container, the children
get rendered.
The effect is disabled if
presentationDirection
is set
to "exiting"
StarPresentation.tsxtsx
import {getBoundingBox ,translatePath } from '@remotion/paths';import {makeStar } from '@remotion/shapes';import type {TransitionPresentationComponentProps } from '@remotion/transitions';importReact , {useMemo ,useState } from 'react';import {AbsoluteFill ,random } from 'remotion';export typeCustomPresentationProps = {width : number;height : number;};constStarPresentation :React .FC <TransitionPresentationComponentProps <CustomPresentationProps >> = ({children ,presentationDirection ,presentationProgress ,passedProps }) => {constfinishedRadius =Math .sqrt (passedProps .width ** 2 +passedProps .height ** 2) / 2;constinnerRadius =finishedRadius *presentationProgress ;constouterRadius =finishedRadius * 2 *presentationProgress ;const {path } =makeStar ({innerRadius ,outerRadius ,points : 5,});constboundingBox =getBoundingBox (path );consttranslatedPath =translatePath (path ,passedProps .width / 2 -boundingBox .width / 2,passedProps .height / 2 -boundingBox .height / 2,);const [clipId ] =useState (() =>String (random (null)));conststyle :React .CSSProperties =useMemo (() => {return {width : '100%',height : '100%',clipPath :presentationDirection === 'exiting' ?undefined : `url(#${clipId })`,};}, [clipId ,presentationDirection ]);return (<AbsoluteFill ><AbsoluteFill style ={style }>{children }</AbsoluteFill >{presentationDirection === 'exiting' ? null : (<AbsoluteFill ><svg ><defs ><clipPath id ={clipId }><path d ={translatedPath }fill ="black" /></clipPath ></defs ></svg ></AbsoluteFill >)}</AbsoluteFill >);};
StarPresentation.tsxtsx
import {getBoundingBox ,translatePath } from '@remotion/paths';import {makeStar } from '@remotion/shapes';import type {TransitionPresentationComponentProps } from '@remotion/transitions';importReact , {useMemo ,useState } from 'react';import {AbsoluteFill ,random } from 'remotion';export typeCustomPresentationProps = {width : number;height : number;};constStarPresentation :React .FC <TransitionPresentationComponentProps <CustomPresentationProps >> = ({children ,presentationDirection ,presentationProgress ,passedProps }) => {constfinishedRadius =Math .sqrt (passedProps .width ** 2 +passedProps .height ** 2) / 2;constinnerRadius =finishedRadius *presentationProgress ;constouterRadius =finishedRadius * 2 *presentationProgress ;const {path } =makeStar ({innerRadius ,outerRadius ,points : 5,});constboundingBox =getBoundingBox (path );consttranslatedPath =translatePath (path ,passedProps .width / 2 -boundingBox .width / 2,passedProps .height / 2 -boundingBox .height / 2,);const [clipId ] =useState (() =>String (random (null)));conststyle :React .CSSProperties =useMemo (() => {return {width : '100%',height : '100%',clipPath :presentationDirection === 'exiting' ?undefined : `url(#${clipId })`,};}, [clipId ,presentationDirection ]);return (<AbsoluteFill ><AbsoluteFill style ={style }>{children }</AbsoluteFill >{presentationDirection === 'exiting' ? null : (<AbsoluteFill ><svg ><defs ><clipPath id ={clipId }><path d ={translatedPath }fill ="black" /></clipPath ></defs ></svg ></AbsoluteFill >)}</AbsoluteFill >);};
Example usage:
MyComp.tsxtsx
export constMyComp :React .FC = () => {const {width ,height } =useVideoConfig ();return (<TransitionSeries ><TransitionSeries .Sequence durationInFrames ={70}><Letter color ="orange">A</Letter ></TransitionSeries .Sequence ><TransitionSeries .Transition presentation ={customPresentation ({width ,height })}timing ={springTiming ({durationInFrames : 45,config : {damping : 200,},durationRestThreshold : 0.0001,})}/><TransitionSeries .Sequence durationInFrames ={60}><Letter color ="pink">B</Letter ></TransitionSeries .Sequence ></TransitionSeries >);};
MyComp.tsxtsx
export constMyComp :React .FC = () => {const {width ,height } =useVideoConfig ();return (<TransitionSeries ><TransitionSeries .Sequence durationInFrames ={70}><Letter color ="orange">A</Letter ></TransitionSeries .Sequence ><TransitionSeries .Transition presentation ={customPresentation ({width ,height })}timing ={springTiming ({durationInFrames : 45,config : {damping : 200,},durationRestThreshold : 0.0001,})}/><TransitionSeries .Sequence durationInFrames ={60}><Letter color ="pink">B</Letter ></TransitionSeries .Sequence ></TransitionSeries >);};
References
See the source code for already implemented presentations for a useful reference.