Remotion LabRemotion Lab
返回模板庫

訂閱 CTA 片尾

頻道名稱以彈簧動畫滑入,紅色訂閱按鈕彈跳出現,搭配搖擺鈴鐺與按讚圖示,最後提示文字淡入,完整呈現 YouTube 頻道結尾號召行動。

片尾訂閱CTA
提示詞(可直接修改內容)
import React from "react";
import {
  AbsoluteFill,
  interpolate,
  spring,
  useCurrentFrame,
  useVideoConfig,
} from "remotion";

export const SubscribeCtaOutro: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  // 頻道名稱:frame 10-40 從下方滑入
  const channelSpring = spring({
    frame: frame - 10,
    fps,
    config: { damping: 22, stiffness: 120 },
    durationInFrames: 30,
  });
  const channelY = interpolate(channelSpring, [0, 1], [80, 0]);
  const channelOpacity = interpolate(channelSpring, [0, 0.3], [0, 1], {
    extrapolateRight: "clamp",
  });

  // 訂閱按鈕:frame 40-70 scale 0→1 彈出
  const subscribeSpring = spring({
    frame: frame - 40,
    fps,
    config: { damping: 16, stiffness: 180 },
    durationInFrames: 30,
  });
  const subscribeScale = interpolate(subscribeSpring, [0, 1], [0, 1], {
    extrapolateLeft: "clamp",
    extrapolateRight: "clamp",
  });

  // 鈴鐺搖擺:frame 70-100
  const bellProgress = interpolate(frame, [70, 100], [0, 1], {
    extrapolateLeft: "clamp",
    extrapolateRight: "clamp",
  });
  // 搖擺:0→1 映射至旋轉角度(-20 → 20 → 0 的來回)
  const bellRotate = interpolate(
    Math.sin(bellProgress * Math.PI * 3),
    [-1, 1],
    [-20, 20]
  );
  const bellOpacity = interpolate(frame, [65, 75], [0, 1], {
    extrapolateLeft: "clamp",
    extrapolateRight: "clamp",
  });

  // 按讚圖示:frame 100-130 scale 0→1
  const likeSpring = spring({
    frame: frame - 100,
    fps,
    config: { damping: 16, stiffness: 180 },
    durationInFrames: 30,
  });
  const likeScale = interpolate(likeSpring, [0, 1], [0, 1], {
    extrapolateLeft: "clamp",
    extrapolateRight: "clamp",
  });

  // 提示文字:frame 130-160 fade in
  const hintOpacity = interpolate(frame, [130, 160], [0, 1], {
    extrapolateLeft: "clamp",
    extrapolateRight: "clamp",
  });

  // 純 CSS 鈴鐺
  const Bell: React.FC = () => (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
        transform: `rotate(${bellRotate}deg)`,
        transformOrigin: "top center",
      }}
    >
      {/* 鈴鐺圓弧頂部 */}
      <div
        style={{
          width: 44,
          height: 44,
          borderRadius: "50% 50% 0 0",
          background: "#ffffff",
          position: "relative",
        }}
      />
      {/* 鈴鐺身體矩形 */}
      <div
        style={{
          width: 52,
          height: 20,
          background: "#ffffff",
          borderRadius: "0 0 6px 6px",
          marginTop: -2,
        }}
      />
      {/* 鈴鐺底部小圓 */}
      <div
        style={{
          width: 14,
          height: 14,
          borderRadius: "50%",
          background: "#ffffff",
          marginTop: -2,
        }}
      />
    </div>
  );

  return (
    <AbsoluteFill
      style={{
        background: "#0f0f0f",
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
        justifyContent: "center",
        gap: 0,
      }}
    >
      {/* 頻道名稱 */}
      <div
        style={{
          transform: `translateY(${channelY}px)`,
          opacity: channelOpacity,
          fontSize: 72,
          fontWeight: 800,
          color: "#ffffff",
          fontFamily: "sans-serif",
          letterSpacing: "-1px",
          marginBottom: 48,
        }}
      >
        我的頻道名稱
      </div>

      {/* 訂閱按鈕 + 鈴鐺 + 按讚 水平排列 */}
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: 32,
          marginBottom: 48,
        }}
      >
        {/* 訂閱按鈕 */}
        <div
          style={{
            transform: `scale(${subscribeScale})`,
            background: "#ff0000",
            color: "#ffffff",
            fontFamily: "sans-serif",
            fontWeight: 700,
            fontSize: 28,
            borderRadius: 4,
            padding: "16px 32px",
            letterSpacing: "1px",
          }}
        >
          訂閱
        </div>

        {/* 純 CSS 鈴鐺 */}
        <div style={{ opacity: bellOpacity }}>
          <Bell />
        </div>

        {/* 按讚圖示 */}
        <div
          style={{
            transform: `scale(${likeScale})`,
            fontSize: 56,
            lineHeight: 1,
          }}
        >
          👍
        </div>
      </div>

      {/* 提示文字 */}
      <div
        style={{
          opacity: hintOpacity,
          fontSize: 24,
          color: "#aaaaaa",
          fontFamily: "sans-serif",
          letterSpacing: "0.5px",
        }}
      >
        記得開啟通知,不錯過任何新影片!
      </div>
    </AbsoluteFill>
  );
};

登入後查看完整程式碼