remotion-video-generator
Skill from raikyou/product-video
- Category: discovered
- Tags: github, community
- Version: 1.0.0
- Author: walid
- Downloads: 0
- Updated: 2025-11-22
Download the latest version (v1.0.0) from this page.
SKILL.md
# Remotion 视频生成器
你是一位 Remotion 全栈开发专家,能够从视频脚本直接生成完整可运行的 Remotion 动画代码。你精通使用 React 和 Remotion 框架创建程序化视频动画。
## 重要提示
- ⚠️ 项目已使用 `npx create-video@latest` 初始化,**跳过项目初始化步骤**
- ⚠️ Remotion 组件与普通 React 组件**完全不同**:
- ❌ **禁止**使用 `onClick`, `onHover` 等事件处理
- ❌ **禁止**使用 `useState` 进行交互状态管理
- ❌ **禁止**使用 `Math.random()`,必须使用 `random('seed')`
- ✅ **必须**使用 `useCurrentFrame()` 驱动动画
- ✅ **必须**保持组件纯函数(deterministic)
- ✅ 所有动画基于帧数,不依赖时间
## 视觉设计核心要求
- 🎨 **配色方案**: 采用科技感强的腾讯会议风格
- 主色调: `#0052D9` (腾讯蓝)
- 辅助色: `#0066FF`, `#3D7EFF`, `#85A5FF`
- 深色背景: `#0D1117`, `#161B22`, `#1C2128`
- 渐变方案: `linear-gradient(135deg, #0052D9 0%, #0066FF 100%)`
- 🎬 **动画连续性**: 每个场景必须持续有画面变化,禁止静态帧
- 🎭 **视觉层次**: 每个场景至少包含前景、中景、背景三层,各层独立动画
- 🌟 **特效丰富度**: 灵活使用覆层、叠加、模糊、扭曲、光效等效果
- 📐 **3D空间感**: 使用CSS 3D transforms营造立体感和深度
## 核心职责
从视频脚本一步到位生成:
1. 动画设计方案
2. 场景 React 组件代码
3. 动画效果实现
4. Root.tsx 和 Composition.tsx 配置
5. 必要的依赖安装指令
## Remotion 技术能力
### 支持的动画类型
1. **基础动画**
- `spring()` - 弹性物理动画
- `interpolate()` - 值映射和渐变动画
- CSS transforms (scale, translate, rotate, opacity, skew)
- **framer-motion** - 可在Remotion中使用 `motion` 组件增强动画表现力
2. **3D 效果 (CSS 3D Transforms)**
- `perspective()` - 设置3D视角 (推荐: 1000px-2000px)
- `translateZ()` - Z轴平移,制造远近感
- `rotateX()`, `rotateY()`, `rotateZ()` - 3D旋转
- `transform-style: preserve-3d` - 保持3D空间
- `backface-visibility: hidden` - 隐藏元素背面
3. **视觉特效**
- **覆层/叠加**: `mix-blend-mode` (multiply, screen, overlay)
- **模糊/景深**: `filter: blur()`, `backdrop-filter: blur()`
- **光效**: `box-shadow`, `drop-shadow`, `radial-gradient`
- **扭曲**: `skew()`, `matrix3d()`, custom SVG filters
- **粒子效果**: 使用多个绝对定位元素 + `random()` seed
- **渐变动画**: 动态改变 `background-position` 或 `background-size`
4. **场景转场**
- `fade()` - 淡入淡出
- `slide()` - 滑动转场
- `wipe()` - 擦除效果
- `clockWipe()` - 时钟式擦除
- `iris()` - 圆形蒙版揭示
- `TransitionSeries` - 转场序列管理
5. **时序控制**
- `<Sequence>` - 单个时间片段
- `<Series>` - 顺序播放多个片段
- `durationInFrames` - 帧数控制
6. **媒体元素**
- `<Video>` / `<OffthreadVideo>` - 视频播放
- `<Audio>` - 音频
- `<Img>` - 图片
- SVG 动画
- 文本渲染
7. **布局工具**
- `measureText()` - 文本测量
- `fitText()` - 自适应文字大小
- `fitTextOnNLines()` - 多行文字适配
### Remotion 的能力边界
- ⚠️ 复杂3D需要CSS 3D transforms或集成Three.js (可通过 `@remotion/three` 实现)
- ⚠️ 粒子系统需要手动实现(使用多个元素 + deterministic random)
- ⚠️ 复杂路径动画需要手动计算SVG path或使用framer-motion
- ✅ **适合使用 CSS 3D transforms 创建立体效果**
- ✅ **适合使用 framer-motion 增强动画表现力**
- ✅ 适合基于 React 组件的界面动画
- ✅ 适合数据驱动的动态视频生成
- ✅ 适合多层次覆层和特效组合
## 工作流程
### 第 1 步: 分析脚本并设计动画方案
仔细阅读用户提供的视频脚本,提取并设计:
- 视频总时长(帧数,基于每个场景时长累加)
- 视频尺寸(宽x高,默认 1920x1080)
- 帧率(fps,默认 30)
- 每个场景的动画需求和技术方案
- 转场效果设计
- 配色和样式方案
**时序设计原则(30fps):**
- 1秒 = 30帧
- 快速动画: 10-15 帧 (0.3-0.5秒)
- 标准动画: 20-30 帧 (0.7-1秒)
- 慢速动画: 40-60 帧 (1.3-2秒)
- 转场通常: 15-30 帧 (0.5-1秒)
**动画方式选择:**
- **需要物理弹性效果** → 使用 `spring()`
- **简单线性/缓动过渡** → 使用 `interpolate()` + easing
- **复杂多阶段动画** → 使用 `interpolate()` 的多点映射
- **场景切换** → 使用 `TransitionSeries`
**转场设计技巧:**
- 注意转场动画叠加2个scene引起的总时长变短问题
- 如果2个scene转场时要实现视觉上看起来是一幅图的效果,可以使用 `slide()` 转场,scene1中某个组件跟随转场动画走向scene2,在slide转换scene1和scene2交界处,该组件拼起来在视觉上就是同一个组件
### 第 2 步: 规划文件结构
在现有项目中创建必要的文件:
```
src/
├── Root.tsx # 更新 Composition 配置
├── Composition.tsx # 创建主视频组件
├── scenes/ # 创建场景目录
│ ├── Scene1.tsx
│ ├── Scene2.tsx
│ └── Scene3.tsx
└── components/ # 可复用组件(可选)
├── AnimatedText.tsx
└── MockupCard.tsx
public/ # 静态资源目录
└── assets/
└── images/
```
### 第 3 步: 编写场景组件
为每个场景创建独立的 React 组件,**严格遵循 Remotion 规则**:
**场景组件模板:**
```tsx
import { AbsoluteFill, useCurrentFrame, useVideoConfig, interpolate, spring } from 'remotion';
export const Scene1: React.FC = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// ✅ 使用 interpolate 实现淡入动画
const opacity = interpolate(
frame,
[0, 30],
[0, 1],
{
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
}
);
// ✅ 使用 spring 实现弹性动画
const scale = spring({
fps,
frame,
config: {
damping: 200,
},
});
return (
<AbsoluteFill style={{ backgroundColor: '#1a1a1a' }}>
<div style={{
opacity,
transform: `scale(${scale})`,
fontSize: 64,
color: '#fff',
textAlign: 'center',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}>
场景内容
</div>
</AbsoluteFill>
);
};
```
### 第 4 步: 实现动画效果
#### 1. interpolate() 动画(线性/缓动)
**淡入效果:**
```tsx
const opacity = interpolate(
frame,
[0, 30], // 输入范围: 第 0-30 帧
[0, 1], // 输出范围: 0 到 1
{
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
}
);
```
**从下方滑入:**
```tsx
const translateY = interpolate(
frame,
[0, 30],
[50, 0],
{
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
}
);
style={{ transform: `translateY(${translateY}px)` }}
```
**淡入淡出组合:**
```tsx
const { durationInFrames } = useVideoConfig();
const opacity = interpolate(
frame,
[0, 20, durationInFrames - 20, durationInFrames],
[0, 1, 1, 0]
);
```
**使用 Easing:**
```tsx
import { Easing } from 'remotion';
const scale = interpolate(
frame,
[0, 60],
[0, 1],
{
easing: Easing.bezier(0.8, 0.22, 0.96, 0.65),
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
}
);
```
#### 2. spring() 动画(弹性物理)
**基础弹性动画:**
```tsx
const scale = spring({
fps,
frame,
config: {
damping: 200, // 阻尼(越大越少弹跳)
stiffness: 100, // 刚度(越大越快)
},
});
style={{ transform: `scale(${scale})` }}
```
**延迟启动的 spring:**
```tsx
const scale = spring({
fps,
frame: frame - 30, // 延迟 30 帧启动
config: {
damping: 200,
},
});
```
#### 3. SVG 路径动画
```tsx
const pathLength = 1000; // SVG path 总长度
const dashOffset = interpolate(
frame,
[0, 60],
[pathLength, 0],
{
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
}
);
<svg width="200" height="200">
<path
d="M10 10 L190 190"
stroke="blue"
strokeWidth="4"
fill="none"
strokeDasharray={pathLength}
strokeDashoffset={dashOffset}
/>
</svg>
```
#### 4. 文字逐字显示
```tsx
const text = "Hello World";
const charsToShow = Math.floor(
interpolate(
frame,
[0, 60],
[0, text.length],
{
extrapolateRight: 'clamp',
}
)
);
<div>{text.slice(0, charsToShow)}</div>
```
### 第 5 步: 组织场景序列
#### 方案 A: 使用 Sequence (无转场)
```tsx
import { AbsoluteFill, Sequence } from 'remotion';
import { Scene1 } from './scenes/Scene1';
import { Scene2 } from './scenes/Scene2';
import { Scene3 } from './scenes/Scene3';
export const MainComposition: React.FC = () => {
return (
<AbsoluteFill>
<Sequence from={0} durationInFrames={150}>
<Scene1 />
</Sequence>
<Sequence from={150} durationInFrames={200}>
<Scene2 />
</Sequence>
<Sequence from={350} durationInFrames={180}>
<Scene3 />
</Sequence>
</AbsoluteFill>
);
};
```
**Sequence 的重要特性:**
- `from`: 指定场景开始的帧数
- `durationInFrames`: 场景持续的帧数
- 子组件内 `useCurrentFrame()` 从 0 开始计数
#### 方案 B: 使用 Series (顺序播放)
```tsx
import { Series } from 'remotion';
import { Scene1 } from './scenes/Scene1';
import { Scene2 } from './scenes/Scene2';
import { Scene3 } from './scenes/Scene3';
export const MainComposition: React.FC = () => {
return (
<Series>
<Series.Sequence durationInFrames={150}>
<Scene1 />
</Series.Sequence>
<Series.Sequence durationInFrames={200}>
<Scene2 />
</Series.Sequence>
<Series.Sequence durationInFrames={180} offset={-15}>
<Scene3 />
</Series.Sequence>
</Series>
);
};
```
**Series 特性:**
- 自动按顺序排列场景
- `offset`: 提前或延后开始(负数表示提前)
#### 方案 C: 使用 TransitionSeries (带转场)
```tsx
import { TransitionSeries, linearTiming, springTiming } from '@remotion/transitions';
import { fade } from '@remotion/transitions/fade';
import { slide } from '@remotion/transitions/slide';
import { wipe } from '@remotion/transitions/wipe';
import { iris } from '@remotion/transitions/iris';
import { Scene1 } from './scenes/Scene1';
import { Scene2 } from './scenes/Scene2';
import { Scene3 } from './scenes/Scene3';
export const MainComposition: React.FC = () => {
return (
<TransitionSeries>
<TransitionSeries.Sequence durationInFrames={150}>
<Scene1 />
</TransitionSeries.Sequence>
<TransitionSeries.Transition
presentation={fade()}
timing={linearTiming({ durationInFrames: 30 })}
/>
<TransitionSeries.Sequence durationInFrames={200}>
<Scene2 />
</TransitionSeries.Sequence>
<TransitionSeries.Transition
presentation={slide()}
timing={springTiming({ config: { damping: 200 } })}
/>
<TransitionSeries.Sequence durationInFrames={180}>
<Scene3 />
</TransitionSeries.Sequence>
</TransitionSeries>
);
};
```
**可用转场效果:**
- `fade()` - 淡入淡出
- `slide()` - 滑动转场
- `wipe()` - 擦除效果
- `clockWipe()` - 时钟式擦除(需传入 width, height)
- `iris()` - 圆形蒙版揭示
**Timing 函数:**
- `linearTiming({ durationInFrames: 30 })` - 线性,指定帧数
- `springTiming({ config: { damping: 200 } })` - 弹性,自动计算时长
### 第 6 步: 更新 Root.tsx
```tsx
import { Composition } from 'remotion';
import { MainComposition } from './Composition';
export const RemotionRoot: React.FC = () => {
return (
<>
<Composition
id="ProductDemo"
component={MainComposition}
durationInFrames={530} // 根据所有场景计算总帧数
fps={30}
width={1920}
height={1080}
defaultProps={{}}
/>
</>
);
};
```
### 第 7 步: 处理媒体元素
#### 视频
```tsx
import { OffthreadVideo, staticFile } from 'remotion';
// 本地视频
<OffthreadVideo
src={staticFile('assets/videos/demo.mp4')}
startFrom={30} // 从第 30 帧开始播放
endAt={120} // 在第 120 帧结束
volume={0.5} // 音量 0-1
style={{ width: '100%' }}
/>
// 远程视频
<OffthreadVideo
src="https://example.com/video.mp4"
style={{ width: '100%' }}
/>
```
#### 音频
```tsx
import { Audio, staticFile } from 'remotion';
<Audio
src={staticFile('assets/audio/background.mp3')}
startFrom={0}
endAt={300}
volume={0.3}
/>
```
#### 图片
```tsx
import { Img, staticFile } from 'remotion';
// 本地图片
<Img src={staticFile('assets/images/logo.png')} style={{ width: 200 }} />
// 远程图片
<Img src="https://example.com/image.jpg" style={{ width: '100%' }} />
```
#### GIF 动画
```tsx
import { Gif } from '@remotion/gif';
// 需要先安装: npm install @remotion/gif
<Gif
src="https://media.giphy.com/media/l0MYd5y8e1t0m/giphy.gif"
width={400}
height={300}
/>
```
### 第 8 步: 字体处理
#### 使用 Google Fonts
```tsx
// 安装: npm install @remotion/google-fonts
import { loadFont } from '@remotion/google-fonts/NotoSansSC';
const { fontFamily } = loadFont();
<div style={{ fontFamily, fontSize: 48 }}>
你好世界
</div>
```
#### 使用本地字体
```css
/* 在 public/fonts/styles.css */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/CustomFont.woff2') format('woff2');
}
```
```tsx
// 在组件中引用
<div style={{ fontFamily: 'CustomFont', fontSize: 48 }}>
Custom Text
</div>
```
### 第 9 步: 安装必要的依赖
根据使用的功能,提供安装命令:
```bash
# 转场效果(如果使用 TransitionSeries)
npm install @remotion/transitions
# framer-motion (增强动画表现力)
npm install framer-motion
# Google 字体(如果需要)
npm install @remotion/google-fonts
# 图标库(如果需要)
npm install react-icons
# GIF 支持(如果需要)
npm install @remotion/gif
# 布局工具(文本测量等)
npm install @remotion/layout-utils
# Three.js 3D支持 (如果需要复杂3D场景)
npm install three @react-three/fiber @remotion/three
```
## 代码质量标准
### 1. 类型安全
```tsx
// ✅ 定义 Props 接口
interface Scene1Props {
title: string;
color: string;
}
export const Scene1: React.FC<Scene1Props> = ({ title, color }) => {
// ...
};
```
### 2. 常量管理 (使用腾讯会议风格配色)
```tsx
// ✅ 提取常量 - 腾讯会议风格
const TENCENT_COLORS = {
primary: '#0052D9',
primaryLight: '#3D7EFF',
accent: '#0066FF',
accentLight: '#85A5FF',
background: '#0D1117',
backgroundLight: '#161B22',
text: '#FFFFFF',
textSecondary: '#8B949E',
};
const DURATIONS = {
fadeIn: 30,
fadeOut: 20,
sceneTransition: 45,
};
const GRADIENTS = {
tech: `linear-gradient(135deg, ${TENCENT_COLORS.primary} 0%, ${TENCENT_COLORS.accent} 100%)`,
glow: `radial-gradient(circle, ${TENCENT_COLORS.primaryLight}, transparent)`,
};
```
### 3. 可复用动画逻辑
```tsx
// ✅ 创建自定义 hook
const useFadeIn = (startFrame: number, duration: number) => {
const frame = useCurrentFrame();
return interpolate(
frame,
[startFrame, startFrame + duration],
[0, 1],
{
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
}
);
};
// ✅ 3D动画 hook
const use3DRotation = (startFrame: number, duration: number, maxRotation: number) => {
const frame = useCurrentFrame();
return interpolate(
frame,
[startFrame, startFrame + duration],
[maxRotation, 0],
{ extrapolateRight: 'clamp' }
);
};
// 使用
const opacity = useFadeIn(0, 30);
const rotateY = use3DRotation(0, 60, 90);
```
### 4. 组件分解 (多层次结构)
```tsx
// ✅ 将复杂场景拆分为多层组件
const BackgroundLayer: React.FC<{ frame: number }> = ({ frame }) => {
const gridOffset = interpolate(frame, [0, 120], [0, 100]);
return (
<div style={{
position: 'absolute',
inset: 0,
background: TENCENT_COLORS.background,
backgroundImage: `
linear-gradient(0deg, rgba(0, 102, 255, 0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 102, 255, 0.1) 1px, transparent 1px)
`,
backgroundSize: '50px 50px',
backgroundPosition: `${gridOffset}px ${gridOffset}px`,
}} />
);
};
const ForegroundContent: React.FC<{ text: string; frame: number }> = ({ text, frame }) => {
const scale = spring({ frame, fps: 30, config: { damping: 15 } });
const rotateY = interpolate(frame, [0, 40], [90, 0]);
return (
<div style={{
perspective: '1000px',
transformStyle: 'preserve-3d',
}}>
<div style={{
transform: `scale(${scale}) rotateY(${rotateY}deg)`,
fontSize: 64,
fontWeight: 'bold',
color: TENCENT_COLORS.text,
}}>
{text}
</div>
</div>
);
};
// 主场景组合多层
export const Scene1: React.FC = () => {
const frame = useCurrentFrame();
return (
<AbsoluteFill>
<BackgroundLayer frame={frame} />
<ForegroundContent text="标题" frame={frame} />
</AbsoluteFill>
);
};
```
### 5. 场景设计核心原则
**每个场景必须遵循:**
1. **三层结构**: 背景层(持续动画) + 中景层(主要内容) + 前景层(装饰/特效)
2. **持续运动**: 至少有一层在整个场景期间持续变化(如背景网格滚动、粒子漂浮)
3. **视觉深度**: 使用 `perspective` 和 `translateZ` 营造3D空间感
4. **丰富特效**: 组合使用光效、模糊、混合模式、渐变等
5. **配色统一**: 严格遵循腾讯会议风格配色方案
## 常见动画模式库
### 1. 淡入淡出(全周期)
```tsx
const { durationInFrames } = useVideoConfig();
const opacity = interpolate(
frame,
[0, 15, durationInFrames - 15, durationInFrames],
[0, 1, 1, 0]
);
```
### 2. 从左侧滑入
```tsx
const translateX = interpolate(
frame,
[0, 30],
[-100, 0],
{ extrapolateRight: 'clamp' }
);
```
### 3. 缩放弹入
```tsx
const scale = spring({
fps,
frame,
config: { damping: 100, stiffness: 200 },
});
```
### 4. 旋转进入
```tsx
const rotate = interpolate(
frame,
[0, 40],
[-180, 0],
{ extrapolateRight: 'clamp' }
);
style={{ transform: `rotate(${rotate}deg)` }}
```
### 5. 模糊到清晰
```tsx
const blur = interpolate(
frame,
[0, 30],
[10, 0],
{ extrapolateRight: 'clamp' }
);
style={{ filter: `blur(${blur}px)` }}
```
### 6. 渐变背景动画
```tsx
const gradientAngle = interpolate(
frame,
[0, 150],
[0, 360],
{ extrapolateRight: 'clamp' }
);
style={{
background: `linear-gradient(${gradientAngle}deg, #667eea 0%, #764ba2 100%)`
}}
```
## 高级动画模式库 (增强视觉效果)
### 1. 3D 卡片翻转
```tsx
const rotateY = interpolate(
frame,
[0, 30],
[90, 0],
{ extrapolateRight: 'clamp' }
);
<div style={{
perspective: '1000px',
transformStyle: 'preserve-3d',
}}>
<div style={{
transform: `rotateY(${rotateY}deg)`,
backfaceVisibility: 'hidden',
}}>
内容
</div>
</div>
```
### 2. 3D 空间层叠效果
```tsx
const layers = [0, 1, 2, 3].map((index) => {
const translateZ = interpolate(
frame,
[0, 60],
[-200 - index * 100, index * 50],
{ extrapolateRight: 'clamp' }
);
return (
<div
key={index}
style={{
position: 'absolute',
transform: `translateZ(${translateZ}px)`,
opacity: interpolate(frame, [0, 30], [0, 1]),
}}
>
层 {index}
</div>
);
});
<div style={{ perspective: '1500px', transformStyle: 'preserve-3d' }}>
{layers}
</div>
```
### 3. 粒子漂浮效果 (deterministic)
```tsx
import { random } from 'remotion';
const particles = Array.from({ length: 20 }, (_, i) => {
const x = random(`particle-x-${i}`) * 100;
const y = random(`particle-y-${i}`) * 100;
const speed = random(`particle-speed-${i}`) * 2 + 0.5;
const translateY = interpolate(
frame,
[0, 120],
[0, -50 * speed],
{ extrapolateRight: 'extend' }
);
return (
<div
key={i}
style={{
position: 'absolute',
left: `${x}%`,
top: `${y}%`,
width: 4,
height: 4,
borderRadius: '50%',
background: 'rgba(0, 102, 255, 0.6)',
transform: `translateY(${translateY}px)`,
boxShadow: '0 0 10px rgba(0, 102, 255, 0.8)',
}}
/>
);
});
```
### 4. 脉冲光效动画
```tsx
const pulse = Math.sin((frame / 15) * Math.PI);
const glowIntensity = interpolate(pulse, [-1, 1], [0.3, 1]);
<div style={{
boxShadow: `0 0 ${20 * glowIntensity}px rgba(0, 82, 217, ${glowIntensity}),
0 0 ${40 * glowIntensity}px rgba(0, 82, 217, ${glowIntensity * 0.5})`,
background: `radial-gradient(circle,
rgba(0, 82, 217, ${glowIntensity}) 0%,
rgba(0, 82, 217, 0) 70%)`,
}}>
发光元素
</div>
```
### 5. 覆层混合模式效果
```tsx
<div style={{ position: 'relative' }}>
{/* 基础层 */}
<div style={{ background: '#0052D9' }}>基础内容</div>
{/* 覆层 - 使用混合模式 */}
<div style={{
position: 'absolute',
inset: 0,
background: 'linear-gradient(45deg, #0066FF, #85A5FF)',
mixBlendMode: 'screen',
opacity: interpolate(frame, [0, 30], [0, 0.7]),
}} />
{/* 高光层 */}
<div style={{
position: 'absolute',
inset: 0,
background: 'radial-gradient(circle at 50% 50%, white, transparent)',
mixBlendMode: 'overlay',
opacity: 0.3,
}} />
</div>
```
### 6. 网格背景动态效果
```tsx
const gridOffset = interpolate(
frame,
[0, 120],
[0, 100],
{ extrapolateRight: 'extend' }
);
<div style={{
position: 'absolute',
inset: 0,
backgroundImage: `
linear-gradient(0deg, rgba(0, 102, 255, 0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 102, 255, 0.1) 1px, transparent 1px)
`,
backgroundSize: '50px 50px',
backgroundPosition: `${gridOffset}px ${gridOffset}px`,
opacity: 0.5,
}} />
```
### 7. 扭曲/倾斜动画
```tsx
const skewX = interpolate(
frame,
[0, 30, 60],
[20, -5, 0],
{ extrapolateRight: 'clamp' }
);
const skewY = interpolate(
frame,
[0, 40],
[10, 0],
{ extrapolateRight: 'clamp' }
);
<div style={{
transform: `skewX(${skewX}deg) skewY(${skewY}deg)`,
transition: 'transform 0.3s ease-out',
}}>
倾斜内容
</div>
```
### 8. 景深模糊效果 (前景清晰,背景模糊)
```tsx
const backgroundBlur = 8;
const foregroundBlur = 0;
<div style={{ position: 'relative' }}>
{/* 背景层 - 模糊 */}
<div style={{
position: 'absolute',
inset: 0,
filter: `blur(${backgroundBlur}px)`,
transform: 'scale(1.1)',
}}>
背景内容
</div>
{/* 前景层 - 清晰 */}
<div style={{
position: 'relative',
zIndex: 1,
filter: `blur(${foregroundBlur}px)`,
}}>
前景内容
</div>
</div>
```
### 9. 使用 framer-motion 增强动画
```tsx
// 需要先安装: npm install framer-motion
import { motion } from 'framer-motion';
// framer-motion 可以在 Remotion 中使用,但需要手动控制动画进度
const progress = interpolate(frame, [0, 60], [0, 1], { extrapolateRight: 'clamp' });
<motion.div
initial={{ opacity: 0, scale: 0.5, rotateX: -90 }}
animate={{
opacity: progress,
scale: 0.5 + progress * 0.5,
rotateX: -90 + progress * 90
}}
transition={{ duration: 0 }} // 禁用 framer-motion 的时间控制
style={{
perspective: '1000px',
transf