Transform3D
The Transform3D class provides a mathematically correct way to compose 3D transformations using matrix operations and quaternions. This eliminates gimbal lock and provides smooth interpolation for 3D animations.
Import
Section titled “Import”import { Transform3D, Vector3, Quaternion } from "remotion-bits";Construction
Section titled “Construction”new Transform3D(options?)
Section titled “new Transform3D(options?)”Creates a new transform from position, rotation, and scale.
const transform = new Transform3D({ position: new Vector3(10, 20, 30), rotation: new Quaternion(0, 0, 0, 1), scale: new Vector3(1, 1, 1),});Transform3D.identity()
Section titled “Transform3D.identity()”Creates an identity transform (no transformation).
const identity = Transform3D.identity();Transform3D.fromEuler(x, y, z, position?, scale?, order?)
Section titled “Transform3D.fromEuler(x, y, z, position?, scale?, order?)”Creates a transform from Euler angles (in radians).
const transform = Transform3D.fromEuler( Math.PI / 2, // 90° X rotation 0, 0, new Vector3(10, 20, 30), // position new Vector3(1, 1, 1), // scale 'XYZ' // rotation order);Parameters:
x,y,z: Rotation in radians around each axisposition: Optional Vector3 for position (default: origin)scale: Optional Vector3 for scale (default: 1,1,1)order: Rotation order (‘XYZ’, ‘XZY’, ‘YXZ’, ‘YZX’, ‘ZXY’, ‘ZYX’)
Transform3D.fromMatrix(matrix)
Section titled “Transform3D.fromMatrix(matrix)”Creates a transform by decomposing a Matrix4.
import { Matrix4 } from "remotion-bits";
const matrix = new Matrix4();const transform = Transform3D.fromMatrix(matrix);Chainable Operations
Section titled “Chainable Operations”All operations return a new transform, leaving the original unchanged.
translate(x, y, z)
Section titled “translate(x, y, z)”Adds a translation offset.
const moved = transform.translate(10, 20, 30);rotate(quaternion)
Section titled “rotate(quaternion)”Applies a rotation quaternion.
import { Quaternion, Vector3 } from "remotion-bits";
const q = new Quaternion().setFromAxisAngle( new Vector3(0, 1, 0), // Y axis Math.PI / 4 // 45° rotation);const rotated = transform.rotate(q);rotateX(radians), rotateY(radians), rotateZ(radians)
Section titled “rotateX(radians), rotateY(radians), rotateZ(radians)”Rotates around a specific axis.
const rotated = transform .rotateX(Math.PI / 4) .rotateY(Math.PI / 6) .rotateZ(Math.PI / 8);scaleBy(sx, sy, sz)
Section titled “scaleBy(sx, sy, sz)”Multiplies the scale.
const scaled = transform.scaleBy(2, 2, 2);multiply(other)
Section titled “multiply(other)”Combines two transforms (matrix multiplication).
const parent = Transform3D.fromEuler(0, Math.PI / 4, 0);const child = Transform3D.identity().translate(10, 0, 0);
// Combine transformsconst world = parent.multiply(child);inverse()
Section titled “inverse()”Returns the inverse transformation.
const inverted = transform.inverse();const identity = transform.multiply(inverted);Interpolation
Section titled “Interpolation”lerp(target, alpha)
Section titled “lerp(target, alpha)”Interpolates between two transforms with proper quaternion SLERP.
const from = Transform3D.identity();const to = Transform3D.fromEuler(Math.PI, 0, 0);
const halfway = from.lerp(to, 0.5);Benefits:
- Smooth rotation paths (spherical interpolation)
- No gimbal lock artifacts
- Mathematically correct scaling
interpolateTransform(from, to, progress, easing?)
Section titled “interpolateTransform(from, to, progress, easing?)”Helper function for transform interpolation with optional easing.
import { interpolateTransform } from "remotion-bits";
const interpolated = interpolateTransform( transformA, transformB, frame / 100, (t) => t * t // easing function);interpolateTransformKeyframes(keyframes, progress, easing?)
Section titled “interpolateTransformKeyframes(keyframes, progress, easing?)”Interpolates through multiple keyframe transforms.
import { interpolateTransformKeyframes } from "remotion-bits";
const keyframes = [ Transform3D.identity(), Transform3D.fromEuler(Math.PI / 2, 0, 0), Transform3D.fromEuler(Math.PI, Math.PI / 2, 0),];
const current = interpolateTransformKeyframes( keyframes, frame / 200);Point Transformation
Section titled “Point Transformation”apply(point)
Section titled “apply(point)”Transforms a Vector3 point.
import { Vector3 } from "remotion-bits";
const point = new Vector3(10, 0, 0);const transformed = transform.apply(point);Conversion
Section titled “Conversion”toMatrix4()
Section titled “toMatrix4()”Converts to a three.js Matrix4.
const matrix = transform.toMatrix4();toCSSMatrix3D()
Section titled “toCSSMatrix3D()”Converts to a CSS matrix3d() string.
const css = transform.toCSSMatrix3D();// "matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,10,20,30,1)"
element.style.transform = css;toEuler(order?)
Section titled “toEuler(order?)”Converts rotation to Euler angles.
const euler = transform.toEuler('XYZ');console.log(euler.x, euler.y, euler.z); // radiansdecompose()
Section titled “decompose()”Returns the transform components.
const { position, rotation, scale } = transform.decompose();Properties
Section titled “Properties”position: Vector3 - The translation componentrotation: Quaternion - The rotation componentscale: Vector3 - The scale component
Usage with Scene3D
Section titled “Usage with Scene3D”While Scene3D components accept numeric props, you can use Transform3D for advanced use cases:
import { Scene3D, Element3D, Transform3D } from "remotion-bits";
// Build transform with chainable APIconst transform = Transform3D.identity() .translate(100, 50, -200) .rotateY(Math.PI / 4) .scaleBy(1.5, 1.5, 1.5);
// Apply to element<Element3D> <div style={{ transform: transform.toCSSMatrix3D(), transformStyle: "preserve-3d" }}> Content </div></Element3D>Common Patterns
Section titled “Common Patterns”Hierarchical Transforms
Section titled “Hierarchical Transforms”// Parent transformconst parent = Transform3D.fromEuler(0, Math.PI / 4, 0) .translate(100, 0, 0);
// Child relative to parentconst child = Transform3D.identity() .translate(50, 0, 0);
// Combine for world positionconst worldTransform = parent.multiply(child);Orbiting Objects
Section titled “Orbiting Objects”const orbitTransform = (angle: number, radius: number) => { const x = Math.cos(angle) * radius; const z = Math.sin(angle) * radius;
return Transform3D.identity() .translate(x, 0, z) .rotateY(angle + Math.PI / 2);};
// Use in animationconst angle = (frame / 60) * Math.PI * 2;const transform = orbitTransform(angle, 200);Smooth Camera Paths
Section titled “Smooth Camera Paths”// Define camera keyframesconst keyframes = [ Transform3D.identity(), Transform3D.fromEuler(0, Math.PI / 2, 0, new Vector3(200, 0, 0)), Transform3D.fromEuler(0, Math.PI, 0, new Vector3(200, 0, 200)),];
// Interpolate smoothlyconst cameraTransform = interpolateTransformKeyframes( keyframes, frame / durationInFrames);Benefits Over Component-Based Transforms
Section titled “Benefits Over Component-Based Transforms”- No Gimbal Lock: Quaternion-based rotation eliminates gimbal lock artifacts
- Smooth Interpolation: Natural spherical interpolation paths
- Composable: Proper matrix multiplication for hierarchical transforms
- Mathematically Correct: Single matrix operation vs. multiple CSS transforms
- Type-Safe: Full TypeScript support with three.js types
- Chainable: Build complex transforms step-by-step
See Also
Section titled “See Also”- Scene3D - 3D scene with camera system
- Element3D - 3D positioned elements
- Transform3D Showcase - Live examples