Leader Line Captions
雜誌編輯式引線圖說:編號圖說沿邊欄排列,以 SVG 引線連至圖中細節點,進場逐條描繪、hover 聚焦壓暗。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
0.14
0.5
0.55
<LeaderLineCaptions />
安裝
npx shadcn@latest add https://webberui.com/r/leader-line-captions.json或在 components.json 設定 registries 後,改用 @webberui/leader-line-captions 安裝。
安裝依賴後,從 registry JSON(/r/leader-line-captions.json 的 files[0].content)複製 leader-line-captions.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge使用
image 傳入任意圖片節點(<img>、漸層 div 皆可),captions 以百分比座標標出圖中細節點,元件會自動編號並描繪引線。
import { LeaderLineCaptions } from "@/components/ui/leader-line-captions";
<LeaderLineCaptions
image={<img src="/product.jpg" alt="產品外觀" />}
side="right"
captions={[
{ x: 30, y: 24, title: "鏡頭模組", description: "三鏡頭矩陣排列。" },
{ x: 68, y: 52, title: "機身邊框", description: "航太級鋁合金。" },
{ x: 44, y: 82, title: "揚聲孔" },
]}
/>每則圖說的 x / y 是相對於圖片的百分比(0–100),與圖片實際尺寸無關,縮放時引線會自動重新對齊。
受控聚焦
不傳 activeIndex 時為非受控,hover 或 focus 圖說即自動聚焦。需要與外部狀態同步時,傳入 activeIndex 並搭配 onActiveChange:
const [active, setActive] = React.useState<number | null>(null);
<LeaderLineCaptions
image={<img src="/map.jpg" alt="地圖" />}
activeIndex={active}
onActiveChange={setActive}
captions={captions}
/>Props
LeaderLineCaptions
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
image | React.ReactNode | — | 圖片內容,於圖框內滿版鋪滿 |
captions | LeaderCaption[] | — | 編號圖說清單,依序自動編號 1…n |
side | "left" | "right" | "right" | 圖說邊欄位置 |
aspectRatio | string | "4 / 3" | 圖框長寬比(CSS aspect-ratio 值) |
stagger | number | 0.14 | 引線逐條描繪的間隔(秒) |
delay | number | 0.1 | 進場前延遲(秒) |
drawDuration | number | 0.5 | 單條引線描繪時長(秒) |
once | boolean | true | 只在第一次進入視口時播放進場動畫 |
activeIndex | number | null | — | 受控聚焦索引;不傳則為非受控 |
defaultActiveIndex | number | null | null | 非受控模式的初始聚焦索引 |
onActiveChange | (index: number | null) => void | — | 聚焦變更時觸發 |
dimOpacity | number | 0.55 | 聚焦時非聚焦畫面的壓暗強度(0–1) |
className | string | — | 外層 figure 的自訂類別 |
LeaderCaption
| 欄位 | 型別 | 說明 |
|---|---|---|
x | number | 對應細節點的水平位置(圖片寬度百分比,0–100) |
y | number | 對應細節點的垂直位置(圖片高度百分比,0–100) |
title | React.ReactNode | 圖說標題 |
description | React.ReactNode | 圖說內文(可選) |
id | string | 自訂 key/識別(可選,預設用索引) |
細節
- 引線端點以
getBoundingClientRect即時量測 badge 與圖中細節點的實際位置,並以ResizeObserver觀察容器與邊欄,縮放、換行或字型載入後都會重新對齊。 - 進場時引線以
pathLength由 0 描到 1 逐條浮現,編號在引線描到過半時依序「點亮」。 - hover 或 focus 任一圖說時,該細節點浮現焦點光圈,其餘畫面以徑向漸層壓暗;移出後光圈停在最後位置淡出,不會跳回原點。
可及性
- 圖說邊欄以
<figure>/<figcaption>語意包裹,每則圖說是可聚焦的<button>,鍵盤Tab即可逐則聚焦並觸發對應的畫面聚焦效果。 - 引線
<svg>、焦點光圈與編號小圓皆為裝飾層(aria-hidden),不干擾螢幕報讀;圖說文字本身是可讀內容。 - 使用者系統開啟「減少動態效果」時,引線與編號直接以最終狀態呈現、不播放描繪動畫,聚焦壓暗改為即時切換。