Measuring DOM nodes
If you want to measure a DOM node, you can assign a React Ref to it and then use the getBoundingClientRect()
browser API to get the position and size of the node.
In Remotion, it is not that easy because the <div>
element in which the video is rendered into has a scale()
transform applied to it, which affects the value that you get from getBoundingClientRect()
.
Measure using the useCurrentScale()
hook
From v4.0.111 on, you can use the useCurrentScale()
hook to correct the dimensions of the element.
MyComponent.tsxtsx
import {useCallback ,useEffect ,useState ,useRef } from "react";import {useCurrentScale } from "remotion";export constMyComponent = () => {constref =useRef <HTMLDivElement >(null);const [dimensions ,setDimensions ] =useState <{correctedHeight : number;correctedWidth : number;} | null>(null);constscale =useCurrentScale ();useEffect (() => {if (!ref .current ) {return;}constrect =ref .current .getBoundingClientRect ();setDimensions ({correctedHeight :rect .height /scale ,correctedWidth :rect .width /scale ,});}, [scale ]);return (<div ><div ref ={ref }>Hello World!</div ></div >);};
MyComponent.tsxtsx
import {useCallback ,useEffect ,useState ,useRef } from "react";import {useCurrentScale } from "remotion";export constMyComponent = () => {constref =useRef <HTMLDivElement >(null);const [dimensions ,setDimensions ] =useState <{correctedHeight : number;correctedWidth : number;} | null>(null);constscale =useCurrentScale ();useEffect (() => {if (!ref .current ) {return;}constrect =ref .current .getBoundingClientRect ();setDimensions ({correctedHeight :rect .height /scale ,correctedWidth :rect .width /scale ,});}, [scale ]);return (<div ><div ref ={ref }>Hello World!</div ></div >);};
Versions prior to v4.0.110
To get an accurate measurement, you can render an additional element with a fixed width (say 10px
) and measure it too. Then, you can divide the width of the element by 10
to get the scale factor.
MyComponent.tsxtsx
import {useCallback ,useEffect ,useState ,useRef } from "react";constMEASURER_SIZE = 10;export constMyComponent = () => {constref =useRef <HTMLDivElement >(null);constmeasurer =useRef <HTMLDivElement >(null);const [dimensions ,setDimensions ] =useState <{correctedHeight : number;correctedWidth : number;} | null>(null);useEffect (() => {if (!ref .current || !measurer .current ) {return;}constrect =ref .current .getBoundingClientRect ();constmeasurerRect =measurer .current .getBoundingClientRect ();constscale =measurerRect .width /MEASURER_SIZE ;setDimensions ({correctedHeight :rect .height *scale ,correctedWidth :rect .width *scale ,});}, []);return (<div ><div ref ={ref }>Hello World!</div ><div ref ={measurer }style ={{width :MEASURER_SIZE ,position : "fixed",top : -99999,}}/></div >);};
MyComponent.tsxtsx
import {useCallback ,useEffect ,useState ,useRef } from "react";constMEASURER_SIZE = 10;export constMyComponent = () => {constref =useRef <HTMLDivElement >(null);constmeasurer =useRef <HTMLDivElement >(null);const [dimensions ,setDimensions ] =useState <{correctedHeight : number;correctedWidth : number;} | null>(null);useEffect (() => {if (!ref .current || !measurer .current ) {return;}constrect =ref .current .getBoundingClientRect ();constmeasurerRect =measurer .current .getBoundingClientRect ();constscale =measurerRect .width /MEASURER_SIZE ;setDimensions ({correctedHeight :rect .height *scale ,correctedWidth :rect .width *scale ,});}, []);return (<div ><div ref ={ref }>Hello World!</div ><div ref ={measurer }style ={{width :MEASURER_SIZE ,position : "fixed",top : -99999,}}/></div >);};
Example project
Versions prior to v4.0.103
In previous versions of Remotion, getBoundingClientRect()
could return dimensions with all values being 0
in the first useEffect()
due to mounting your component but not showing it.
Going forward, you can rely on the dimensions being non-zero.
See also
- react-use-measure - Measure elements correctly inside a scroll container