資料展示

Animated Beam

節點間流動光束,適合整合示意圖與資料流動畫。

在任意兩個節點之間繪製一條會流動的光束,路徑隨容器尺寸自動重算,最適合畫整合示意圖、資料管線與架構圖。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add animated-beam

還沒有專案,或安裝遇到問題?看快速開始 →

Animated Beam 是用 React、SVG 與 Motion(motion/react)做的動態連線光束(animated beam/流程連接線)元件:依兩個節點的實際位置畫出直線或二次貝茲曲線,再讓一段漸層亮光沿線流動。常用來畫整合架構圖、資料流向或「多個來源匯入一個平台」的示意圖。

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

0
3
2
編輯中的呼叫預設屬性
<AnimatedBeam/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

適用情境

  • SaaS 首頁的整合區塊:多個第三方服務連到你的產品 logo
  • 說明資料流向的架構圖,例如「使用者、API、資料庫」
  • 開發者工具介紹同步、部署流程,用反向光束表示雙向傳輸
  • 產品功能頁的「運作方式」示意區
  • 不適合:要表達有先後順序、帶文字說明的流程步驟時,改用 Orbit Timeline 或 Stepper 這類有標籤的元件

安裝

npx webberui@latest add https://webberui.com/r/animated-beam.json

或在 components.json 設定 registries 後,改用 @webberui/animated-beam 安裝。

使用

光束是一個絕對定位的疊層,透過三個 ref 量測座標:containerRef 是量測原點,fromRef / toRef 是兩端節點。把節點與光束都放進同一個 relative 容器即可。

"use client";

import * as React from "react";
import { AnimatedBeam } from "@/components/ui/animated-beam";

export function Diagram() {
  const containerRef = React.useRef<HTMLDivElement>(null);
  const fromRef = React.useRef<HTMLDivElement>(null);
  const toRef = React.useRef<HTMLDivElement>(null);

  return (
    <div ref={containerRef} className="relative flex justify-between p-10">
      <div ref={fromRef} className="size-11 rounded-full bg-white" />
      <div ref={toRef} className="size-11 rounded-full bg-white" />
      <AnimatedBeam
        containerRef={containerRef}
        fromRef={fromRef}
        toRef={toRef}
      />
    </div>
  );
}

節點需要有實際尺寸與定位;光束以 -z-10 疊在節點之下,請確保容器帶 relative。多條光束用不同的 delay 錯開流動時序,用 curvature 讓匯聚到同一樞紐的線條散開。

範例

多個來源匯入同一個樞紐

左側每個節點各接一條光束到中央節點。用不同的 curvature 讓線條散開,用 delay 錯開流動時間。

"use client";

import * as React from "react";
import { AnimatedBeam } from "@/components/ui/animated-beam";

const sources = ["表單", "金流", "客服"];

export function IntegrationDiagram() {
  const containerRef = React.useRef<HTMLDivElement>(null);
  const hubRef = React.useRef<HTMLDivElement>(null);
  const sourceRefs = [
    React.useRef<HTMLDivElement>(null),
    React.useRef<HTMLDivElement>(null),
    React.useRef<HTMLDivElement>(null),
  ];

  return (
    <div ref={containerRef} className="relative isolate flex items-center justify-between p-10">
      <div className="flex flex-col gap-8">
        {sources.map((label, i) => (
          <div key={label} ref={sourceRefs[i]} className="rounded-lg border bg-white px-3 py-2 text-sm">
            {label}
          </div>
        ))}
      </div>
      <div ref={hubRef} className="size-14 rounded-full border bg-white" />
      {sourceRefs.map((ref, i) => (
        <AnimatedBeam
          key={i}
          containerRef={containerRef}
          fromRef={ref}
          toRef={hubRef}
          curvature={(1 - i) * 40}
          delay={i * 0.4}
        />
      ))}
    </div>
  );
}

雙向傳輸

兩個節點之間放兩條光束:一條正向、一條 reverse,並用 Y 偏移把線拉開,避免重疊。

<AnimatedBeam
  containerRef={containerRef}
  fromRef={appRef}
  toRef={serverRef}
  startYOffset={-8}
  endYOffset={-8}
  curvature={20}
/>
<AnimatedBeam
  containerRef={containerRef}
  fromRef={appRef}
  toRef={serverRef}
  startYOffset={8}
  endYOffset={8}
  curvature={-20}
  reverse
/>

自訂顏色與線寬

gradientStartColor、gradientStopColor 控制流動亮光的漸層,pathColor 與 pathOpacity 控制底下的靜態軌道。

<AnimatedBeam
  containerRef={containerRef}
  fromRef={fromRef}
  toRef={toRef}
  pathWidth={3}
  pathColor="#a3a3a3"
  pathOpacity={0.3}
  gradientStartColor="#f97316"
  gradientStopColor="#facc15"
  duration={4}
/>

Props

Prop型別預設值說明
containerRefRefObject<HTMLElement | null>—量測座標用的外層容器
fromRefRefObject<HTMLElement | null>—光束起點節點
toRefRefObject<HTMLElement | null>—光束終點節點
curvaturenumber0曲率(px):正值上拱、負值下沉
reversebooleanfalse反向流動(終點朝起點)
durationnumber3單次流動時長(秒)
delaynumber0進場前延遲(秒)
pathColorstring"currentColor"靜態底線顏色
pathWidthnumber2線寬(px)
pathOpacitynumber0.15底線透明度
gradientStartColorstring"#818cf8"流動漸層起點色
gradientStopColorstring"#22d3ee"流動漸層終點色
startXOffsetnumber0起點 X 微調(px)
startYOffsetnumber0起點 Y 微調(px)
endXOffsetnumber0終點 X 微調(px)
endYOffsetnumber0終點 Y 微調(px)

可及性

  • 使用者系統開啟「減少動態效果」時,只保留靜態底線、不播放流動亮點
  • 光束層帶 aria-hidden,純裝飾不干擾輔助科技
  • 路徑透過 ResizeObserver 監聽容器尺寸變化,RWD 下自動重算,離開時清理

常見問題

可以在 Next.js App Router 使用嗎?

可以。檔案開頭已有 "use client",但因為要建立 ref,包住節點與光束的那個元件也要是用戶端元件,如上方範例開頭的 "use client"。路徑在 effect 裡量測,伺服器端渲染時是空路徑。

為什麼看不到光束?

先確認容器有 relative,節點有實際尺寸。光束以 -z-10 疊在節點下方,如果容器本身有背景色,光束可能被蓋住;在容器加上 isolate 建立新的堆疊脈絡即可。

版面改變時路徑會更新嗎?

容器尺寸改變時會透過 ResizeObserver 重算。只監看容器,若節點自己移動但容器尺寸不變(例如節點本身有位移動畫),路徑不會跟著更新。

支援減少動態效果嗎?

支援。系統開啟「減少動態效果」時,只顯示靜態底線,不播放流動亮光。整個 SVG 帶 aria-hidden,不會被螢幕閱讀器讀到。

需要哪些依賴?

motion、clsx 與 tailwind-merge。也可以從安裝區塊的「手動」分頁複製原始碼。