Skip to content

WrapperPlant 植栽包裝器設計文件

概述

使用 SVG Path 渲染植物,L-System 文法生成分支結構,遞迴分支展開做生長動畫。首個植物種類為長草(Grass)。

技術選型

面向選擇原因
渲染SVG Path向量清晰、CSS transform 擺動動畫天然契合、z-index 易控制
生成演算法L-System換規則即可切換植物種類,生長動畫天然適合逐代展開
生長動畫遞迴分支展開stroke-dashoffset 逐段描繪,按深度依序觸發
擺動動畫CSS keyframes + rotatetransform-origin 固定根部,不同分支差異化 delay

元件結構

wrapper-plant/
├── wrapper-plant.vue        # 主元件:容器、slot、SVG 層、Intersection Observer
├── use-l-system.ts          # L-System 文法解析與迭代
├── use-plant-renderer.ts    # 將 L-System 結果轉為 SVG path 資料
├── use-plant-growth.ts      # 生長動畫控制(逐段展開 + 時序)
├── plant-presets.ts          # 預設植物規則(grass、未來的 ivy、sprout)
├── index.ts                 # 型別匯出
└── examples/
    └── basic-usage.vue

L-System 設計

typescript
interface LSystemRule {
  axiom: string
  ruleMap: Map<string, string>
  angle: number
  iterations: number
  lengthFactor: number
}

符號語義:F 前進畫線、+ 左轉、- 右轉、[ 壓入狀態、] 彈出狀態。

SVG 渲染

  • L-System 指令轉為一系列 SVG <path> 元素,每段分支一個 path
  • 每個 path 記錄深度(generation)與繪製順序,用於控制生長動畫先後
  • 莖用較粗的 stroke-width,隨深度遞減變細
  • 葉片用簡單的橢圓或弧線 path,附加在末端分支

生長動畫

  1. stroke-dasharray + stroke-dashoffset 做每段 path 的描繪動畫
  2. 按深度排序:主莖 → 一級分支 → 二級分支 → 葉片,依序觸發
  3. 每段之間微小延遲,產生遞迴展開視覺效果
  4. CSS transition 或 anime.js 控制 easing

隨風擺動

  • 每個分支 path 設定 transform-origin 在根部
  • CSS @keyframes + rotate() 正弦波擺動
  • 不同分支不同 animation-delayanimation-duration(隨機偏移)
  • 深層分支擺動幅度略大於主莖

觸發機制

  • 預設使用 Intersection Observer,進入視窗後觸發
  • delay prop 控制進入視窗後延遲多少 ms 才開始生長
  • immediate prop 可切換為掛載即觸發

API 設計

Props

Prop型別預設值說明
position'top' | 'bottom' | 'left' | 'right''bottom'植物長出的方位
preset'grass''grass'預設植物種類
densitynumber5植物叢數量
zIndexnumber-1植物在內容上方或下方
delaynumber0進入視窗後延遲觸發(ms)
immediatebooleanfalse掛載即觸發
swayingbooleantrue啟用隨風擺動
growthDurationnumber2000生長動畫時長(ms)

Emits

EventPayload說明
growth-start生長動畫開始
growth-end生長動畫結束

Expose Methods

Method說明
grow()手動觸發生長
reset()重置為未生長狀態

Slots

Slot說明
default被包裝的內容物

位置與自動適應

  • 元件用 position: relative 包裹 slot 內容
  • SVG 層用 position: absolute + overflow: visible 覆蓋在容器上
  • 根據 position prop 決定 SVG 定位與植物生長方向
  • useElementBounding() 監聽容器大小,動態調整植物分佈範圍

v0.67.0