Remotion LabRemotion Lab
視覺設計噪聲視覺化效果

噪聲視覺化效果

使用 @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 噪聲

所有函式返回 -11 之間的值。

浮動點陣網格示範

以下範例展示如何使用 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()-11 的輸出範圍映射到所需的值範圍

參見