diff --git a/apps/videos/src/components/GitHubCTA.tsx b/apps/videos/src/components/GitHubCTA.tsx new file mode 100644 index 00000000..9bd83ea6 --- /dev/null +++ b/apps/videos/src/components/GitHubCTA.tsx @@ -0,0 +1,103 @@ +import type React from "react"; +import { AbsoluteFill, Img, interpolate, staticFile, useCurrentFrame } from "remotion"; +import { ClipReveal } from "@/components/ClipReveal"; +import { COLOR } from "@/lib/colors"; +import { FONT, TEXT } from "@/lib/fonts"; + +export const GitHubCTA: React.FC<{ + labelFrame?: number; + logoFrame?: number; + taglineFrame?: number; + ctaFrame?: number; + urlFrame?: number; +}> = ({ labelFrame = 0, logoFrame = 15, taglineFrame = 30, ctaFrame = 50, urlFrame = 65 }) => { + const frame = useCurrentFrame(); + + const logoScale = interpolate(frame, [logoFrame, logoFrame + 15], [0, 1], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + + const glowRadius = interpolate(frame, [logoFrame, logoFrame + 15], [0, 200], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + + const borderOpacity = interpolate(Math.sin(frame * 0.06), [-1, 1], [0.3, 0.6]); + + return ( + + + + 100% OPEN SOURCE + + + +
+ +
+
+ +
+ +
+ + + Free forever. + + +
+ + +
+ + + + + Star us on GitHub + +
+
+ +
+ + + + github.com/snapotter-hq/SnapOtter + + + + ); +}; diff --git a/apps/videos/src/components/LogoReveal.tsx b/apps/videos/src/components/LogoReveal.tsx new file mode 100644 index 00000000..c8188c00 --- /dev/null +++ b/apps/videos/src/components/LogoReveal.tsx @@ -0,0 +1,140 @@ +import type React from "react"; +import { + AbsoluteFill, + Img, + interpolate, + random, + spring, + staticFile, + useCurrentFrame, + useVideoConfig, +} from "remotion"; +import { ClipReveal } from "@/components/ClipReveal"; +import { COLOR } from "@/lib/colors"; +import { TEXT } from "@/lib/fonts"; +import { SPRING } from "@/lib/motion"; + +const PARTICLE_COUNT = 25; + +export const LogoReveal: React.FC<{ + convergeFrame?: number; + burstFrame?: number; + logoFrame?: number; + textFrame?: number; + taglineFrame?: number; + logoSize?: number; +}> = ({ + convergeFrame = 0, + burstFrame = 30, + logoFrame = 30, + textFrame = 50, + taglineFrame = 70, + logoSize = 80, +}) => { + const frame = useCurrentFrame(); + const { fps, width, height } = useVideoConfig(); + + const logoScale = spring({ + frame: frame - logoFrame, + fps, + config: SPRING.popIn, + }); + + const glowRadius = interpolate(frame, [burstFrame, burstFrame + 15], [0, 200], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + const glowOpacity = interpolate(frame, [burstFrame, burstFrame + 20], [0.2, 0], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + + return ( + + {Array.from({ length: PARTICLE_COUNT }).map((_, i) => { + const baseAngle = random(`particle-angle-${i}`) * Math.PI * 2; + const maxRadius = 300 + random(`particle-radius-${i}`) * 200; + const size = 2 + random(`particle-size-${i}`) * 3; + const rotSpeed = 0.03 + random(`particle-speed-${i}`) * 0.02; + const particleOpacity = 0.3 + random(`particle-opacity-${i}`) * 0.7; + + const convergeProgress = interpolate(frame, [convergeFrame, burstFrame], [1, 0], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + + const angle = baseAngle + frame * rotSpeed; + const radius = maxRadius * convergeProgress; + const px = width / 2 + Math.cos(angle) * radius; + const py = height / 2 + Math.sin(angle) * radius; + const pOpacity = convergeProgress > 0.05 ? particleOpacity : 0; + + return ( +
+ ); + })} + +
+ + + +
+ + + SnapOtter + + +
+ + + + Your images. Stay yours. + + + + ); +};