先來看第一版
短暫的過場卡片:巨大漸層數字「1」以彈簧動畫衝入畫面,接著「第一版」文字與眼睛圖示漸入,搭配閃爍光點列,邀請觀眾一睹第一版成果。
過場動畫版本展示視覺設計教學
提示詞(可直接修改內容)
import React from "react";
import {
AbsoluteFill,
useCurrentFrame,
useVideoConfig,
interpolate,
spring,
} from "remotion";
const colors = {
background: "#0A0E14",
backgroundGradient: "linear-gradient(135deg, #0A0E14 0%, #131A24 100%)",
accent: "#00D4AA",
accentSecondary: "#4DA3FF",
warning: "#FFB547",
danger: "#FF6B6B",
};
const fonts = { main: "'Inter', 'Noto Sans TC', sans-serif" };
export const Scene73-FirstVersion: React.FC = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const numberSpring = spring({ frame: Math.max(0, frame - 5), fps, config: { damping: 8, mass: 0.6, stiffness: 130 } });
const numberScale = interpolate(numberSpring, [0, 1], [0.2, 1]);
const numberOpacity = interpolate(numberSpring, [0, 0.3], [0, 1], { extrapolateRight: "clamp" });
const ringSpring = spring({ frame: Math.max(0, frame - 10), fps, config: { damping: 10, mass: 0.8, stiffness: 90 } });
const ringScale = interpolate(ringSpring, [0, 1], [0.4, 1]);
const ringOpacity = interpolate(ringSpring, [0, 0.5], [0, 0.35], { extrapolateRight: "clamp" });
const textSpring = spring({ frame: Math.max(0, frame - 30), fps, config: { damping: 10, mass: 0.5, stiffness: 120 } });
const textTranslateY = interpolate(textSpring, [0, 1], [30, 0]);
const textOpacity = interpolate(textSpring, [0, 0.4], [0, 1], { extrapolateRight: "clamp" });
const eyeSpring = spring({ frame: Math.max(0, frame - 45), fps, config: { damping: 10, mass: 0.4, stiffness: 140 } });
const eyeScale = interpolate(eyeSpring, [0, 1], [0, 1]);
const eyeOpacity = interpolate(eyeSpring, [0, 0.4], [0, 1], { extrapolateRight: "clamp" });
const sparkleBase = frame > 50 ? frame - 50 : 0;
const fadeOut = interpolate(frame, [95, 120], [1, 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
const glowPulse = interpolate(Math.sin(frame * 0.05), [-1, 1], [0.04, 0.1]);
return (
<AbsoluteFill style={{ background: colors.backgroundGradient }}>
<div style={{ position: "absolute", top: "50%", left: "50%", width: 800, height: 800, borderRadius: "50%", background: `radial-gradient(circle, ${colors.accent}18 0%, transparent 65%)`, transform: "translate(-50%, -50%)", opacity: glowPulse * fadeOut * 10 }} />
<AbsoluteFill style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", opacity: fadeOut, gap: 0 }}>
<div style={{ position: "absolute", display: "flex", alignItems: "center", justifyContent: "center", opacity: ringOpacity * fadeOut, transform: `scale(${ringScale})` }}>
<svg width="510" height="510" viewBox="0 0 340 340">
<defs>
<linearGradient id="fvRingGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stopColor={colors.accent} stopOpacity={0.6} />
<stop offset="100%" stopColor={colors.accentSecondary} stopOpacity={0.2} />
</linearGradient>
</defs>
<circle cx="170" cy="170" r="155" fill="none" stroke="url(#fvRingGrad)" strokeWidth="2" strokeDasharray="12 8" />
<circle cx="170" cy="170" r="138" fill="none" stroke={colors.accent} strokeWidth="1" opacity={0.15} />
</svg>
</div>
<div style={{ transform: `scale(${numberScale})`, opacity: numberOpacity, marginBottom: 0, lineHeight: 1 }}>
<span style={{ fontSize: 420, fontWeight: 900, fontFamily: fonts.main, background: `linear-gradient(135deg, ${colors.accent} 0%, ${colors.accentSecondary} 100%)`, WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", filter: `drop-shadow(0 0 40px ${colors.accent}60)`, display: "block", lineHeight: 1 }}>1</span>
</div>
<div style={{ display: "flex", alignItems: "center", gap: 30, marginTop: 12, opacity: textOpacity, transform: `translateY(${textTranslateY}px)` }}>
<span style={{ fontSize: 78, fontWeight: 700, fontFamily: fonts.main, color: "rgba(255,255,255,0.88)", letterSpacing: 6 }}>第一版</span>
<div style={{ transform: `scale(${eyeScale})`, opacity: eyeOpacity, display: "flex", alignItems: "center" }}>
<svg width="72" height="72" viewBox="0 0 48 48">
<defs>
<linearGradient id="fvEyeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stopColor={colors.accent} />
<stop offset="100%" stopColor={colors.accentSecondary} />
</linearGradient>
</defs>
<path d="M4 24 C10 12, 38 12, 44 24 C38 36, 10 36, 4 24 Z" fill="none" stroke="url(#fvEyeGrad)" strokeWidth="2.5" strokeLinecap="round" />
<circle cx="24" cy="24" r="7" fill="url(#fvEyeGrad)" opacity={0.9} />
<circle cx="24" cy="24" r="3.5" fill={colors.background} />
<circle cx="27" cy="21" r="1.5" fill="white" opacity={0.7} />
</svg>
</div>
</div>
{sparkleBase > 0 && (
<div style={{ marginTop: 42, opacity: textOpacity * 0.7 }}>
<svg width="360" height="30" viewBox="0 0 240 20">
{[0, 1, 2, 3, 4, 5].map((i) => {
const sparkleOp = interpolate(Math.sin(sparkleBase * 0.1 + i * 1.1), [-1, 1], [0.15, 0.75]);
const isAccent = i % 2 === 0;
return <circle key={i} cx={20 + i * 40} cy={10} r={isAccent ? 3 : 2} fill={isAccent ? colors.accent : colors.accentSecondary} opacity={sparkleOp} />;
})}
</svg>
</div>
)}
</AbsoluteFill>
</AbsoluteFill>
);
};登入後查看完整程式碼