← back to Prestige Car Wash Video

src/BrowserShot.tsx

100 lines

import { AbsoluteFill, Img, staticFile, useCurrentFrame, interpolate, Easing } from 'remotion';
import type { Section } from './sections';

const FONT = 'Inter, "SF Pro Display", system-ui, -apple-system, sans-serif';

// A macOS-style browser window that "Ken Burns" pans/zooms the captured page.
export const BrowserShot: React.FC<{ s: Section }> = ({ s }) => {
  const frame = useCurrentFrame();

  // window geometry on the 1920x1080 stage
  const FRAME_W = 1560;
  const CHROME_H = 46;
  const VIEW_H = 748;
  const nativeW = s.w || 1440;
  const nativeH = s.h || 900;
  const scale = FRAME_W / nativeW;
  const scaledH = nativeH * scale;

  const dur = s.frames;
  // vertical pan for tall pages; gentle zoom for short ones
  const overflow = Math.max(0, scaledH - VIEW_H);
  const eased = interpolate(frame, [0, dur], [0, 1], {
    easing: Easing.inOut(Easing.ease),
    extrapolateRight: 'clamp',
  });
  const translateY = overflow > 8 ? -overflow * eased : 0;
  const zoom = overflow > 8 ? 1 : interpolate(eased, [0, 1], [1.0, 1.05]);

  // whole-window intro: rise + settle
  const rise = interpolate(frame, [0, 18], [40, 0], {
    easing: Easing.out(Easing.cubic),
    extrapolateRight: 'clamp',
  });

  return (
    <AbsoluteFill style={{ alignItems: 'center', justifyContent: 'flex-start' }}>
      <div
        style={{
          marginTop: 74 + rise,
          width: FRAME_W,
          borderRadius: 16,
          overflow: 'hidden',
          boxShadow: '0 40px 120px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.06)',
          background: '#0f1a2b',
        }}
      >
        {/* browser chrome */}
        <div
          style={{
            height: CHROME_H,
            display: 'flex',
            alignItems: 'center',
            gap: 10,
            padding: '0 16px',
            background: 'linear-gradient(#182740,#111d31)',
            borderBottom: '1px solid rgba(255,255,255,0.06)',
          }}
        >
          <Dot c="#ff5f57" /><Dot c="#febc2e" /><Dot c="#28c840" />
          <div
            style={{
              marginLeft: 14,
              flex: 1,
              height: 26,
              borderRadius: 8,
              background: 'rgba(255,255,255,0.06)',
              display: 'flex',
              alignItems: 'center',
              padding: '0 12px',
              color: '#9fb3cd',
              fontFamily: FONT,
              fontSize: 14,
              letterSpacing: 0.2,
            }}
          >
            <span style={{ opacity: 0.6, marginRight: 8 }}>🔒</span>
            {s.url}
          </div>
        </div>
        {/* viewport */}
        <div style={{ height: VIEW_H, overflow: 'hidden', background: '#0b1220' }}>
          <Img
            src={staticFile(s.file!)}
            style={{
              width: FRAME_W,
              transform: `translateY(${translateY}px) scale(${zoom})`,
              transformOrigin: 'top center',
              display: 'block',
            }}
          />
        </div>
      </div>
    </AbsoluteFill>
  );
};

const Dot: React.FC<{ c: string }> = ({ c }) => (
  <div style={{ width: 12, height: 12, borderRadius: 12, background: c }} />
);