噪聲視覺化效果
使用 @remotion/noise 套件在 Remotion 影片中加入噪聲視覺化效果,包括浮動點陣網格等動態效果。
噪聲視覺化效果
使用 @remotion/noise 套件,你可以在影片中加入噪聲(Noise)視覺化效果,創造有機的、流暢的動態效果。
安裝
npm install @remotion/noise核心概念
Perlin Noise 與 Simplex Noise
噪聲函式(noise functions)是用來生成看起來自然、平滑的隨機值的演算法。與純隨機數不同,噪聲函式生成的相鄰值之間有平滑的過渡,這使得它非常適合用於:
- 有機動畫效果
- 地形生成
- 粒子系統
- 流體模擬視覺效果
@remotion/noise 提供以下函式:
noise2D(seed, x, y):2D 噪聲noise3D(seed, x, y, z):3D 噪聲(常用 z 軸表示時間)noise4D(seed, x, y, z, w):4D 噪聲
所有函式返回 -1 到 1 之間的值。
浮動點陣網格示範
以下範例展示如何使用 noise3D() 函式創建一個浮動點陣網格「表面」效果:
- 第 1、2 維度用於空間域(位置)
- 第 3 維度用於時間域(動畫)
import { noise3D } from "@remotion/noise";
import React from "react";
import { interpolate, useCurrentFrame, useVideoConfig } from "remotion";
const OVERSCAN_MARGIN = 100;
const ROWS = 10;
const COLS = 15;
type NoiseCompProps = {
speed: number;
circleRadius: number;
maxOffset: number;
};
const NoiseComp: React.FC<NoiseCompProps> = ({
speed,
circleRadius,
maxOffset,
}) => {
const frame = useCurrentFrame();
const { height, width } = useVideoConfig();
return (
<svg width={width} height={height}>
{new Array(COLS).fill(0).map((_, i) =>
new Array(ROWS).fill(0).map((__, j) => {
// 計算基礎位置
const x = i * ((width + OVERSCAN_MARGIN) / COLS);
const y = j * ((height + OVERSCAN_MARGIN) / ROWS);
// 歸一化位置(0 到 1)
const px = i / COLS;
const py = j / ROWS;
// 使用噪聲函式計算位移
// 每個點使用不同的 seed,確保 x 和 y 方向獨立移動
const dx = noise3D("x", px, py, frame * speed) * maxOffset;
const dy = noise3D("y", px, py, frame * speed) * maxOffset;
// 計算透明度
const opacity = interpolate(
noise3D("opacity", i, j, frame * speed),
[-1, 1],
[0, 1]
);
const key = `${i}-${j}`;
return (
<circle
key={key}
cx={x + dx}
cy={y + dy}
r={circleRadius}
fill="gray"
opacity={opacity}
/>
);
})
)}
</svg>
);
};設定合成
在 Root.tsx 中使用此元件:
import { Composition } from "remotion";
import { NoiseComp } from "./NoiseComp";
export const Root: React.FC = () => {
return (
<Composition
id="NoiseVisualization"
component={NoiseComp}
durationInFrames={150}
fps={30}
width={1920}
height={1080}
defaultProps={{
speed: 0.01,
maxOffset: 50,
circleRadius: 5,
}}
/>
);
};常用參數調整
速度(speed)
控制動畫的移動速度:
- 慢速(
speed: 0.005):緩慢流動,適合背景效果 - 中速(
speed: 0.01):標準速度,自然流動感 - 快速(
speed: 0.05):快速律動,適合節奏強烈的音樂
// 慢速背景效果
const speed = 0.005;
// 快速節奏效果
const speed = 0.05;最大位移(maxOffset)
控制每個點偏移基礎位置的最大距離(像素):
- 小值(
maxOffset: 10):微小的振動效果 - 中值(
maxOffset: 50):明顯的流動效果 - 大值(
maxOffset: 150):混亂的波動效果
圓圈半徑(circleRadius)
控制每個點的大小,可以搭配噪聲動態改變:
// 動態改變圓圈大小
const radius = interpolate(
noise3D("radius", px, py, frame * speed),
[-1, 1],
[2, 12]
);進階效果:彩色噪聲點陣
結合顏色變化創造更豐富的視覺效果:
import { noise3D } from "@remotion/noise";
import { interpolate, useCurrentFrame, useVideoConfig } from "remotion";
const COLS = 20;
const ROWS = 12;
export const ColorNoise: React.FC<{
speed: number;
}> = ({ speed = 0.01 }) => {
const frame = useCurrentFrame();
const { width, height } = useVideoConfig();
return (
<svg width={width} height={height} style={{ background: "#0a0a0a" }}>
{new Array(COLS).fill(0).map((_, i) =>
new Array(ROWS).fill(0).map((__, j) => {
const x = (i / COLS) * width;
const y = (j / ROWS) * height;
const t = frame * speed;
// 使用不同 seed 計算不同屬性
const hue = interpolate(
noise3D("hue", i / COLS, j / ROWS, t),
[-1, 1],
[0, 360]
);
const saturation = interpolate(
noise3D("sat", i / COLS, j / ROWS, t),
[-1, 1],
[50, 100]
);
const lightness = interpolate(
noise3D("light", i / COLS, j / ROWS, t),
[-1, 1],
[30, 70]
);
const radius = interpolate(
noise3D("r", i / COLS, j / ROWS, t),
[-1, 1],
[4, 18]
);
return (
<circle
key={`${i}-${j}`}
cx={x + (width / COLS) / 2}
cy={y + (height / ROWS) / 2}
r={radius}
fill={`hsl(${hue}, ${saturation}%, ${lightness}%)`}
/>
);
})
)}
</svg>
);
};噪聲波浪效果
使用噪聲創建有機的波浪效果:
import { noise2D } from "@remotion/noise";
import { useCurrentFrame, useVideoConfig } from "remotion";
const WAVE_POINTS = 100;
export const NoiseWave: React.FC<{
amplitude: number;
speed: number;
color: string;
}> = ({ amplitude = 80, speed = 0.02, color = "#4ecdc4" }) => {
const frame = useCurrentFrame();
const { width, height } = useVideoConfig();
const centerY = height / 2;
// 生成波浪點
const points = new Array(WAVE_POINTS + 1).fill(0).map((_, i) => {
const x = (i / WAVE_POINTS) * width;
const nx = i / WAVE_POINTS;
// 使用 2D 噪聲:x 軸為空間位置,y 軸為時間
const y = centerY + noise2D("wave", nx * 3, frame * speed) * amplitude;
return `${x},${y}`;
});
// 建立填充多邊形
const polygonPoints = [
`0,${height}`,
...points,
`${width},${height}`,
].join(" ");
return (
<svg width={width} height={height}>
<polygon points={polygonPoints} fill={color} opacity={0.7} />
</svg>
);
};注意事項
noise3D的 seed 參數(第一個參數)是字串,用來區分不同屬性的噪聲,確保各屬性獨立變化- 噪聲函式的輸入值應保持在合理範圍內,避免數值過大導致重複的視覺模式
- 使用
interpolate()將-1到1的輸出範圍映射到所需的值範圍