feat: add marketing video mode and Remotion marketing video project
Add debug-only Marketing Video Mode toggle that enables hands-free screen recording across the app: auto-scrolling Featured Trips carousel, auto-filling trip wizard, smooth trip detail scrolling via CADisplayLink, and trip options auto-sort with scroll. Add Remotion marketing video project with 6 scene compositions using image sequences extracted from screen recordings, varied phone entrance animations, and deduped frames for smooth playback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
71
marketing-videos/src/components/KineticText.tsx
Normal file
71
marketing-videos/src/components/KineticText.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import React from "react";
|
||||
import { interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion";
|
||||
import { THEME } from "../theme";
|
||||
|
||||
type KineticTextProps = {
|
||||
words: string[];
|
||||
fontSize?: number;
|
||||
color?: string;
|
||||
delay?: number;
|
||||
staggerFrames?: number;
|
||||
textShadow?: string;
|
||||
textAlign?: "center" | "left" | "right";
|
||||
lineHeight?: number;
|
||||
};
|
||||
|
||||
export const KineticText: React.FC<KineticTextProps> = ({
|
||||
words,
|
||||
fontSize = 72,
|
||||
color = THEME.colors.white,
|
||||
delay = 0,
|
||||
staggerFrames = 3,
|
||||
textShadow = THEME.textShadow,
|
||||
textAlign = "center",
|
||||
lineHeight = 1.2,
|
||||
}) => {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
justifyContent: textAlign === "center" ? "center" : "flex-start",
|
||||
gap: `0 ${fontSize * 0.25}px`,
|
||||
fontFamily: THEME.font.heading,
|
||||
fontSize,
|
||||
fontWeight: 800,
|
||||
color,
|
||||
textShadow,
|
||||
lineHeight,
|
||||
}}
|
||||
>
|
||||
{words.map((word, i) => {
|
||||
const wordDelay = delay + i * staggerFrames;
|
||||
|
||||
const entrance = spring({
|
||||
frame: frame - wordDelay,
|
||||
fps,
|
||||
config: { damping: 14, mass: 0.6, stiffness: 140 },
|
||||
});
|
||||
|
||||
const opacity = interpolate(entrance, [0, 1], [0, 1]);
|
||||
const translateY = interpolate(entrance, [0, 1], [30, 0]);
|
||||
|
||||
return (
|
||||
<span
|
||||
key={`${word}-${i}`}
|
||||
style={{
|
||||
display: "inline-block",
|
||||
opacity,
|
||||
transform: `translateY(${translateY}px)`,
|
||||
}}
|
||||
>
|
||||
{word}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user