Remotion 教程 10:用 Skia 做高级 2D 图形和光效
DOM 和 CSS 很适合做图文排版,但遇到复杂光效、路径、粒子、手绘风和动态图形时,会越来越难维护。Skia 适合解决这类高级 2D 绘制问题。
推荐组合:
@remotion/skia
@shopify/react-native-skiaSkia 负责绘制,Remotion 负责时间。
Skia 适合什么视频
优先考虑 Skia 的场景:
- 粒子和光效。
- 复杂路径动画。
- 手绘风线条。
- 动态海报和动态图形。
- 大量形状叠加。
- DOM 难以高效表达的 2D 画面。
不建议一开始就用 Skia 做所有东西。标题、字幕、卡片、普通图文排版,用 DOM 更直接。
动画还是由 frame 控制
Skia 负责绘制,但动画数值仍然来自 Remotion:
const frame = useCurrentFrame();
const radius = interpolate(frame, [0, 75, 150], [34, 108, 34]);
const x = interpolate(frame, [0, 150], [140, 500]);这段代码表示:
圆的半径在 34 -> 108 -> 34 之间变化
圆的 x 坐标从 140 移动到 500Skia 不需要自己维护时间。每一帧的圆心和半径都由 Remotion 算出来。
完整最小示例
下面是一个 Skia 光效画布:背景是渐变,前景有几个叠加发光圆。
import React from "react";
import {
Canvas,
Circle,
Group,
LinearGradient,
Rect,
vec,
} from "@shopify/react-native-skia";
import { interpolate, useCurrentFrame } from "remotion";
export const SkiaArtwork: React.FC = () => {
const frame = useCurrentFrame();
const radius = interpolate(frame, [0, 75, 150], [34, 108, 34]);
const x = interpolate(frame, [0, 150], [140, 500]);
return (
<Canvas style={{ width: 640, height: 460 }}>
<Rect x={0} y={0} width={640} height={460}>
<LinearGradient
start={vec(0, 0)}
end={vec(640, 460)}
colors={["#111827", "#312e81", "#0f766e"]}
/>
</Rect>
<Group blendMode="screen">
<Circle cx={x} cy={220} r={radius} color="#38bdf8" opacity={0.72} />
<Circle
cx={640 - x / 2}
cy={170}
r={72}
color="#f59e0b"
opacity={0.58}
/>
<Circle cx={250} cy={310} r={54} color="#a78bfa" opacity={0.64} />
</Group>
</Canvas>
);
};这里的 blendMode="screen" 会让颜色产生更接近光效叠加的视觉效果。
Web 环境要等待 Skia 加载
Skia Web 需要加载 wasm。渲染视频时不能在 Skia 还没准备好时截图,所以需要用 delayRender() 等待:
const { continueRender, delayRender } = useDelayRender();
const renderHandle = useMemo(
() => delayRender("加载 Skia Web 和示例图形"),
[delayRender],
);
useEffect(() => {
LoadSkiaWeb({ locateFile: (file) => `/${file}` })
.then(() => import("./SkiaArtwork"))
.then((module) => {
setArtwork(() => module.default);
window.requestAnimationFrame(() => {
continueRender(renderHandle);
});
});
}, [continueRender, renderHandle]);这个配置比普通 DOM 组件复杂,所以 Skia 适合在确实需要高级绘制时再引入。
工程注意点
项目里还需要在 remotion.config.ts 启用 Skia:
Config.overrideWebpackConfig((currentConfiguration) => {
return enableSkia(enableTailwind(currentConfiguration));
});如果忘了这一步,Skia Web 渲染很容易失败。
示例项目位置
这篇文章对应示例项目里的:
Composition: LessonSkiaEcosystem
文件: src/lessons/SkiaEcosystem.tsx
文件: src/lessons/SkiaArtwork.tsx
配置: remotion.config.ts运行示例项目后,可以尝试:
- 把
radius的最大值从 108 改成 150。 - 把
x的终点从 500 改成 560。 - 修改一个
Circle的颜色,观察光效变化。
下一篇看 D3:数据视频里,怎么把数据映射和逐帧动画分开。