Files
novalon-website/docs/superpowers/specs/2026-05-03-hero-ink-data-morph-design.md
T

196 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Hero 数字水墨动画设计规格
> 日期:2026-05-03
> 状态:待审查
> 决策者:张翔
## 1. 需求与场景
### 背景
当前 Hero 区域(`hero-section-v2.tsx`)使用纯白背景 + 基础 FadeUp 文字动画,视觉表现力不足,缺乏品牌辨识度。
### 目标
为 Hero 区域添加"数字水墨"动画效果,传达"传统智慧 → 数字化转型"的品牌叙事。
### 成功标准
- Hero 入场时有明确的三阶段动画叙事(墨粒扩散 → 沉淀 → 数据化)
- 动画在 60fps 下流畅运行,移动端无卡顿
- `prefers-reduced-motion` 下优雅降级
- 动画播放完毕后零持续 CPU 开销
- 与现有 Hero 文字内容无视觉冲突
### 约束
- 纯入场动画,无鼠标/滚动交互
- 零新增外部依赖(纯 Canvas 2D API
- 遵循项目现有特效组件模式(`src/components/effects/`
## 2. 技术选型
**方案:Canvas 2D 粒子系统**
| 维度 | 评价 |
|------|------|
| 视觉效果 | 120-200 粒子 + 墨晕 + 连接线,效果完整 |
| 性能 | Canvas 2D 渲染 200 粒子无压力,移动端流畅 |
| 兼容性 | Canvas 2D 全浏览器支持,无 WebGL 依赖 |
| 包体积 | 零依赖,< 5KB gzipped |
| 可维护性 | 状态机驱动三阶段,逻辑清晰 |
| 项目一致性 | 与 DataParticleFlow、SubtleParticles 等现有组件模式一致 |
排除方案:SVG + CSS 动画(feTurbulence 滤镜移动端不稳定,三阶段叙事难以用 CSS 实现)
## 3. 组件设计
### 3.1 新组件:InkDataMorph
**文件**`src/components/effects/ink-data-morph.tsx`
```tsx
interface InkDataMorphProps {
particleCount?: number; // 默认 150
primaryColor?: string; // 墨色,默认 '#1C1C1C'
accentColor?: string; // 朱砂红,默认 '#C41E3A'
connectionColor?: string; // 连接线色,默认 '#C41E3A'
connectionDistance?: number; // 连接线触发距离,默认 80px
className?: string;
}
```
**渲染**:绝对定位 `<canvas>` 元素,`pointer-events: none``aria-hidden="true"`
### 3.2 三阶段状态机
```
Phase 1: SPREADING (0s ~ 2s)
├── 墨粒从两个中心点向外扩散
├── 粒子带有机随机速度 + 方向
├── 大粒子附带墨晕光晕(径向渐变)
└── 25% 粒子为朱砂红色
Phase 2: SETTLING (2s ~ 3.5s)
├── 粒子速度衰减至接近静止
├── 透明度缓慢降低(模拟墨汁沉淀)
└── 整体画面趋于稳定
Phase 3: MORPHING (3.5s ~ 6s)
├── 粒子缓慢移向目标数据点位置
├── 粒子半径缩小为数据点大小
├── 相邻粒子间浮现连接线(距离 < connectionDistance
└── 最终状态:静态数据网络图
COMPLETE (6s+)
├── 停止 requestAnimationFrame
└── 零持续 CPU 开销
```
### 3.3 粒子数据结构
```ts
interface Particle {
x: number; // 当前 x
y: number; // 当前 y
vx: number; // x 速度
vy: number; // y 速度
radius: number; // 当前半径
initialRadius: number; // 初始半径(墨粒大小)
dataRadius: number; // 数据点目标半径
opacity: number; // 当前透明度
isAccent: boolean; // 是否为朱砂红
phase: 'spreading' | 'settling' | 'morphing' | 'complete';
spreadTime: number;
maxSpreadTime: number;
settleTime: number;
morphProgress: number;
targetX: number; // 数据点目标 x
targetY: number; // 数据点目标 y
}
```
### 3.4 扩散中心点布局
```
┌─────────────────────────────────────────┐
│ ● 中心1 │
│ (70%, 35%) │
│ │
│ 文字区域 ←── │
│ │
│ ● 中心2 │
│ (25%, 65%) │
│ │
└─────────────────────────────────────────┘
```
- 中心1(右上):120 粒子,主墨色
- 中心2(左下):60 粒子,延迟 500ms 启动
- Phase 3 数据点目标位置分布在右侧和下方,不遮挡文字
### 3.5 性能策略
- **2x Canvas 渲染**`canvas.width = clientWidth * 2`CSS 缩放,Retina 清晰
- **连接线优化**:Phase 3 才计算,使用网格空间分区避免 O(n²)
- **一次性动画**Phase 3 完成后停止 rAF
- **`prefers-reduced-motion`**:跳过动画,直接渲染最终静态数据网络图
## 4. Hero Section 集成
### 4.1 修改文件
`src/components/sections/hero-section-v2.tsx`
### 4.2 变更点
| 项目 | 当前 | 改造后 |
|------|------|--------|
| 背景色 | `bg-white` | `bg-[#FAFAF5]`(宣纸暖白) |
| Canvas 层 | 无 | `<InkDataMorph />` 绝对定位 inset-0 z-0 |
| 内容层 z-index | 默认 | `z-10` |
| 品牌标签 delay | 0.1s | 1.6s |
| 标题 delay | 0.2s | 1.9s |
| 副标题 delay | 0.3s | 2.2s |
| 描述 delay | 0.4s | 2.5s |
| 按钮组 delay | 0.5s | 2.8s |
| IntersectionObserver | 保留 | 保留,只在进入视口时启动 Canvas 动画 |
| useReducedMotion | 保留 | 保留,禁用时 Canvas 直接渲染最终状态 |
### 4.3 导入方式
使用 `dynamic import` + `ssr: false`,与项目现有特效组件加载方式一致:
```tsx
const InkDataMorph = dynamic(
() => import('@/components/effects/ink-data-morph').then(mod => ({ default: mod.InkDataMorph })),
{ ssr: false }
);
```
## 5. 测试策略
### 5.1 单元测试(ink-data-morph.test.tsx
- 组件渲染 canvas 元素
- 接受自定义 propsparticleCount, colors 等)
- `prefers-reduced-motion` 下不启动 rAF
- unmount 时清理 rAF
### 5.2 集成测试(hero-section-v2.test.tsx 更新)
- InkDataMorph 在 Hero section 中渲染
- 文字内容 z-index 在 Canvas 之上
- 背景色为 `#FAFAF5`
### 5.3 视觉验证
- `npm run dev` 打开首页,观察三阶段动画
- 移动端视口(375px)验证粒子密度和性能
- `prefers-reduced-motion` 模拟验证降级效果
## 6. 文件清单
| 操作 | 文件 |
|------|------|
| 新建 | `src/components/effects/ink-data-morph.tsx` |
| 新建 | `src/components/effects/ink-data-morph.test.tsx` |
| 修改 | `src/components/sections/hero-section-v2.tsx` |
| 修改 | `src/components/effects/index.ts`(导出新组件) |