影片推薦結尾卡
仿 YouTube 結尾卡版型,「繼續觀看」標題淡入後左右兩個影片推薦框分別從外側滑入,下方頻道頭像以彈跳動畫現身,最後訂閱按鈕彈出,引導觀眾繼續互動。
片尾結尾卡YouTube訂閱
提示詞(可直接修改內容)
import React from "react";
import {
AbsoluteFill,
interpolate,
spring,
useCurrentFrame,
useVideoConfig,
} from "remotion";
// 時間軸
const TITLE-IN = 10; // 「繼續觀看」淡入
const LEFT-CARD-IN = 20; // 左影片框滑入
const RIGHT-CARD-IN = 30; // 右影片框滑入
const AVATAR-IN = 60; // 頻道頭像彈出
const SUB-BTN-IN = 80; // 訂閱按鈕彈入
export const EndScreenOutro: React.FC = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// ── 標題 fade in ──
const titleOpacity = interpolate(frame, [TITLE-IN, TITLE-IN + 25], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
// ── 左影片框:從左滑入 ──
const leftSpring = spring({
frame: frame - LEFT-CARD-IN,
fps,
config: { damping: 20, stiffness: 120 },
});
const leftX = interpolate(leftSpring, [0, 1], [-100, 0]);
const leftOpacity = interpolate(leftSpring, [0, 0.4], [0, 1], {
extrapolateRight: "clamp",
});
// ── 右影片框:從右滑入 ──
const rightSpring = spring({
frame: frame - RIGHT-CARD-IN,
fps,
config: { damping: 20, stiffness: 120 },
});
const rightX = interpolate(rightSpring, [0, 1], [100, 0]);
const rightOpacity = interpolate(rightSpring, [0, 0.4], [0, 1], {
extrapolateRight: "clamp",
});
// ── 頻道頭像:scale 0→1 彈出 ──
const avatarSpring = spring({
frame: frame - AVATAR-IN,
fps,
config: { damping: 14, stiffness: 160 },
});
const avatarScale = interpolate(avatarSpring, [0, 1], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
// ── 訂閱按鈕:彈入 ──
const subSpring = spring({
frame: frame - SUB-BTN-IN,
fps,
config: { damping: 12, stiffness: 200 },
});
const subScale = interpolate(subSpring, [0, 1], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
return (
<AbsoluteFill
style={{
background: "#0f0f0f",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
fontFamily: "sans-serif",
}}
>
{/* 頂部標題 */}
<div
style={{
opacity: titleOpacity,
fontSize: 32,
color: "#ffffff",
letterSpacing: "4px",
fontWeight: 600,
marginBottom: 48,
}}
>
繼續觀看
</div>
{/* 影片佔位框區域 */}
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
gap: 40,
marginBottom: 60,
}}
>
{/* 左影片框 */}
<div
style={{
transform: `translateX(${leftX}px)`,
opacity: leftOpacity,
width: 480,
height: 270,
borderRadius: 12,
background: "#272727",
border: "1px solid #404040",
overflow: "hidden",
position: "relative",
flexShrink: 0,
}}
>
{/* 縮圖佔位(上半部) */}
<div
style={{
width: "100%",
height: 180,
background: "#1a1a1a",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
{/* 縮圖紋理 */}
<div
style={{
width: "100%",
height: "100%",
background: "linear-gradient(135deg, #1f1f1f 25%, #252525 75%)",
}}
/>
</div>
{/* 右上角 play 按鈕 */}
<div
style={{
position: "absolute",
top: 12,
right: 12,
width: 40,
height: 40,
borderRadius: "50%",
background: "rgba(0,0,0,0.75)",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<span style={{ color: "#ffffff", fontSize: 16, marginLeft: 3 }}>▶</span>
</div>
{/* 下半部文字 */}
<div
style={{
padding: "10px 14px",
display: "flex",
flexDirection: "column",
gap: 6,
}}
>
<div
style={{
height: 16,
width: "70%",
borderRadius: 4,
background: "#404040",
}}
/>
<div
style={{
height: 12,
width: "40%",
borderRadius: 4,
background: "#333333",
}}
/>
</div>
</div>
{/* 右影片框 */}
<div
style={{
transform: `translateX(${rightX}px)`,
opacity: rightOpacity,
width: 480,
height: 270,
borderRadius: 12,
background: "#272727",
border: "1px solid #404040",
overflow: "hidden",
position: "relative",
flexShrink: 0,
}}
>
{/* 縮圖佔位(上半部) */}
<div
style={{
width: "100%",
height: 180,
background: "#1a1a1a",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<div
style={{
width: "100%",
height: "100%",
background: "linear-gradient(135deg, #1f2a1f 25%, #1f251f 75%)",
}}
/>
</div>
{/* 右上角 play 按鈕 */}
<div
style={{
position: "absolute",
top: 12,
right: 12,
width: 40,
height: 40,
borderRadius: "50%",
background: "rgba(0,0,0,0.75)",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<span style={{ color: "#ffffff", fontSize: 16, marginLeft: 3 }}>▶</span>
</div>
{/* 下半部文字 */}
<div
style={{
padding: "10px 14px",
display: "flex",
flexDirection: "column",
gap: 6,
}}
>
<div
style={{
height: 16,
width: "60%",
borderRadius: 4,
background: "#404040",
}}
/>
<div
style={{
height: 12,
width: "35%",
borderRadius: 4,
background: "#333333",
}}
/>
</div>
</div>
</div>
{/* 底部:頻道頭像 + 訂閱按鈕 */}
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
gap: 32,
}}
>
{/* 頻道頭像圓形 */}
<div
style={{
transform: `scale(${avatarScale})`,
width: 120,
height: 120,
borderRadius: "50%",
background: "#ff0000",
display: "flex",
alignItems: "center",
justifyContent: "center",
flexShrink: 0,
}}
>
<span style={{ fontSize: 48, color: "#ffffff" }}>▶</span>
</div>
{/* 訂閱按鈕 */}
<div
style={{
transform: `scale(${subScale})`,
background: "#ff0000",
color: "#ffffff",
fontFamily: "sans-serif",
fontWeight: 700,
fontSize: 22,
borderRadius: 40,
padding: "16px 40px",
whiteSpace: "nowrap",
letterSpacing: "1px",
}}
>
訂閱頻道
</div>
</div>
</AbsoluteFill>
);
};登入後查看完整程式碼