Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Apply best practices for creating programmatic videos with Remotion and React
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
rules/assets/text-animations-typewriter.tsx
1import {2AbsoluteFill,3interpolate,4useCurrentFrame,5useVideoConfig,6} from 'remotion';78const COLOR_BG = '#ffffff';9const COLOR_TEXT = '#000000';10const FULL_TEXT = 'From prompt to motion graphics. This is Remotion.';11const PAUSE_AFTER = 'From prompt to motion graphics.';12const FONT_SIZE = 72;13const FONT_WEIGHT = 700;14const CHAR_FRAMES = 2;15const CURSOR_BLINK_FRAMES = 16;16const PAUSE_SECONDS = 1;1718// Ideal composition size: 1280x7201920const getTypedText = ({21frame,22fullText,23pauseAfter,24charFrames,25pauseFrames,26}: {27frame: number;28fullText: string;29pauseAfter: string;30charFrames: number;31pauseFrames: number;32}): string => {33const pauseIndex = fullText.indexOf(pauseAfter);34const preLen =35pauseIndex >= 0 ? pauseIndex + pauseAfter.length : fullText.length;3637let typedChars = 0;38if (frame < preLen * charFrames) {39typedChars = Math.floor(frame / charFrames);40} else if (frame < preLen * charFrames + pauseFrames) {41typedChars = preLen;42} else {43const postPhase = frame - preLen * charFrames - pauseFrames;44typedChars = Math.min(45fullText.length,46preLen + Math.floor(postPhase / charFrames),47);48}49return fullText.slice(0, typedChars);50};5152const Cursor: React.FC<{53frame: number;54blinkFrames: number;55symbol?: string;56}> = ({frame, blinkFrames, symbol = '\u258C'}) => {57const opacity = interpolate(58frame % blinkFrames,59[0, blinkFrames / 2, blinkFrames],60[1, 0, 1],61{extrapolateLeft: 'clamp', extrapolateRight: 'clamp'},62);6364return <span style={{opacity}}>{symbol}</span>;65};6667export const MyAnimation = () => {68const frame = useCurrentFrame();69const {fps} = useVideoConfig();7071const pauseFrames = Math.round(fps * PAUSE_SECONDS);7273const typedText = getTypedText({74frame,75fullText: FULL_TEXT,76pauseAfter: PAUSE_AFTER,77charFrames: CHAR_FRAMES,78pauseFrames,79});8081return (82<AbsoluteFill83style={{84backgroundColor: COLOR_BG,85}}86>87<div88style={{89color: COLOR_TEXT,90fontSize: FONT_SIZE,91fontWeight: FONT_WEIGHT,92fontFamily: 'sans-serif',93}}94>95<span>{typedText}</span>96<Cursor frame={frame} blinkFrames={CURSOR_BLINK_FRAMES} />97</div>98</AbsoluteFill>99);100};101