UNPKG

@fxshelf/card-orbit

Version:

Path-constrained 3D card orbit carousel for React and Vue — rise, arc, exit. No Framer Motion / GSAP. Copy-as-source friendly.

138 lines (101 loc) • 4.17 kB
# 动效说明(专业版) > 大白话版见 [动效说明-大白话.md](./动效说明-大白话.md) 复刻 tasteskill.dev Hero 卡片轨迹:单一标量进度驱动参数化路径采样;指针事件是进度的调制输入,而非自由平面位移。 实现:`src/react/CardOrbit.tsx` · `src/core/path.ts` · `src/core/createOrbit.ts` --- ## 管道总览 ```mermaid flowchart LR A["自动播放 rAF"] --> P["progress ∈ [0,1)"] B["指针拖动"] --> P P --> C["每张卡 phase"] C --> D["分段路径 x,y"] D --> E["depth 包络"] E --> F["CSS transform"] ``` | 概念 | 定义 | |------|------| | 核心模型 | 单一标量 `progress` 驱动路径采样;拖拽为进度的二次输入 | | 位置约束 | 恒为 `f(path(phase(progress)))`,无独立 `(dx, dy)` 位移积分 | | 与动画库关系 | 本 Hero 不依赖 Motion/GSAP 的 drag 路径约束 | --- ## 1. 进度时钟 ```mermaid sequenceDiagram participant rAF as requestAnimationFrame participant Drag as Pointer participant P as progress rAF->>P: 未拖动时 += 45e-6 × dt Drag->>P: 拖动时 += 8e-4 × (dy + 0.25×dx) Note over P: 拖动期间暂停自动推进 ``` 空闲时以固定角速度积分全局进度;交互时切换为指针位移映射的进度增量,并暂停自动积分。 - 自动:`progress = (progress + 45e-6 · Δt) mod 1` - 拖动:`Δ = Δy + 0.25·Δx`,`progress += 8e-4 · Δ` - `setPointerCapture` 保证指针离开元素边界后仍可持续采样 --- ## 2. 相位错开 ```mermaid flowchart TB subgraph loop["单位环 progress"] direction LR C0["卡0"] --- C1["卡1"] --- C2["卡2"] --- C3["卡3"] --- C4["卡4"] --- C5["卡5"] --- C6["卡6"] end ``` 七张卡在单位环上均匀相位偏移: ```ts phase = (i / 7 + progress) % 1 ``` 可见性由窗口函数门控:`phase ∈ (0, 0.72)`。窗口内归一化为路径参数: ```ts local = phase / 0.72 // ∈ [0, 1] ``` --- ## 3. 分段路径 路径弧长权重:上升 `280` · 四分之一圆弧 `(π/2)·90` · 退出 `240`。 **坐标投影演示(动画):** [轨道演示.html](./轨道演示.html) — 以舞台中心为原点,绘制 `x%`/`y%` 平面轨迹与 `local` 示踪点。 ```mermaid flowchart LR R["① 上升直线<br/>x=-10, y 上爬"] --> A["② 四分之一圆<br/>x,y = cos/sin"] A --> X["③ 横向退出<br/>y=70, x 右移"] ``` ```text 上升 (x≈-10) 圆弧 (cos/sin) 退出 (y≈70) │ ╭──╮ ──→ │ ╭──╯ │ ▼ │ │ ●───────────────────●─────●───────────────────● ``` | 段 | 参数化 | |----|--------| | 上升 | 固定 `x=-10` 的线性插值,权重 `280` | | 圆弧 | 极角 180°→270° 的四分之一圆:`x = 80 + 90·cos(θ)`,`y = -20 - 90·sin(θ)` | | 退出 | 固定 `y=70` 的线性水平位移,权重 `240` | 设 `F = 280 / pathLen`,`G = (280 + arc) / pathLen`,则 `local < F` / `< G` / 其余分别落入三段。 --- ## 4. 景深与投影 ```mermaid flowchart TB L["local"] --> S["sin 包络 → depth"] S --> T["translate3d Z / scale / opacity / z-index"] S --> R["rotateX / rotateY"] ST["perspective: 3400px<br/>+ preserve-3d 倾斜"] --> T ``` 沿路径参数施加正弦包络得到标量 `depth`,再线性映射到透视 Z、缩放、透明度与堆叠序。舞台外层 `perspective: 3400px`,内层 `preserve-3d` 施加固定视点倾斜(约 `rotateX(3deg) rotateY(-4deg)`)。 ```ts translate3d( calc(-50% + ${x}%), calc(-50% + ${y}%), ${-1000 + 1280 * depth}px ) rotateX(${4 - 2 * depth}deg) rotateY(${-3 + 6 * local}deg) scale(${0.44 + 0.74 * depth}) ``` --- ## 边界说明 | 非目标 | 实际做法 | |--------|----------| | Motion/GSAP `drag` + 路径约束 | 手写 rAF + 分段函数 | | 每卡独立物理拖拽 | 共享 `progress`;位置为路径求值 | **一句话:** 参数化路径上的进度驱动动画;指针事件是进度的调制输入。