# 核心设计原则

本文档包含所有输出模式共享的核心设计原则和技术规范。

---

## 一、概念聚焦原则

### 一图一概念

- **每张配图只表达 1-2 个核心概念**，避免信息过载
- **视觉突出**：用最大的视觉空间展示最重要的信息
- **简化表达**：去除所有不必要的装饰和说明性文字
- **直击要点**：让观众一眼就能理解核心信息

---

## 二、极简设计风格

### 色彩限制

- 仅使用 1 种主色调（浅蓝、浅绿、浅灰等）
- 避免使用渐变、阴影等复杂效果

### ⚠️ 背景色强制要求

**【前置要求 - 最高优先级】**

SVG 画布 **必须设置非白色背景色**，原因如下：
1. 纯白背景（#FFFFFF）导致圆角、边框等视觉元素与背景融为一体，无法区分
2. 白色背景与文字内容的对比度不足，视觉层次感差
3. 无法体现设计感和专业性

```svg
<!-- ❌ 错误：纯白背景，圆角和边框无法显现 -->
<svg viewBox="0 0 800 450">
  <rect x="60" y="60" width="680" height="330" rx="12" fill="#FFFFFF" stroke="#E0E0E0"/>
</svg>

<!-- ✅ 正确：浅色背景，元素轮廓清晰可见 -->
<svg viewBox="0 0 800 450">
  <rect x="60" y="60" width="680" height="330" rx="12" fill="#F0F4F8" stroke="#D0D8E0"/>
</svg>
```

**选择标准**：
- 背景色必须在 `#F5F5F5` ~ `#FAF0E6` 范围内（米白、浅灰、浅米、浅粉、浅蓝等）
- 背景色与画布内容的主色调形成轻微对比
- 避免使用纯白 `#FFFFFF` 作为画布背景

### ⚠️ 圆角强制要求

**【前置要求 - 最高优先级】**

所有矩形/圆角矩形元素 **必须设置圆角**，禁止使用直角：

**原因**：
1. 直角矩形在浅色背景下与背景融为一体，视觉边界不清晰
2. 圆角传达亲和感与现代感，与极简设计风格一致
3. 圆角矩形作为内容容器时，与背景形成明确的空间层次

```svg
<!-- ❌ 错误：直角矩形，圆角和边框无法显现 -->
<rect x="60" y="60" width="680" height="330" fill="#F0F4F8" stroke="#D0D8E0"/>
<!-- 或 -->
<rect x="60" y="60" width="680" height="330" rx="0" fill="#F0F4F8" stroke="#D0D8E0"/>

<!-- ✅ 正确：标准圆角 8-12px -->
<rect x="60" y="60" width="680" height="330" rx="10" fill="#F0F4F8" stroke="#D0D8E0"/>
```

**圆角规范**：
- 统一使用 `rx="10"`（圆角值必须显式写出）
- 内部元素（如圆形）不需要圆角

### 文字极简

- 标题 ≤ 6 字
- 无其他文字说明
- 所有文本单行显示

### 图形极大化

- 用超大尺寸的几何图形、图标、emoji 作为主要视觉元素
- 采用扁平化风格，避免 3D 效果
- 功能性优先：每个元素都必须有明确目的

---

## 三、尺寸标准

| 元素类型 | 最小尺寸 | 说明 |
|---------|---------|------|
| 标题字体 | 48px | 确保手机端清晰可读 |
| 正文字体 | 24px | 增强可读性 |
| emoji 大小 | 100px | 大幅提升，确保情感表达清晰 |
| 方框/容器高度 | 120px | 提供充足的视觉空间 |
| 圆形元素直径 | 150px | 确保圆形图形清晰可辨 |
| 线条粗细 | 4px | 避免线条过细在手机上消失 |
| **画布尺寸** | **800x450** | **16:9 比例，所有元素按比例放大** |

---

## 四、布局与边界控制

### 画布边界约束

- 画布尺寸：800x450px（16:9 比例）
- 安全边界：上下左右各保留 60px 安全边距
- 有效绘制区域：680x330px
- **绝对禁止内容超出画布边界**（最高优先级）

### 内容长度限制

- 标题：最多 6 个中文字符（约 120px 宽度）
- 标签文字：最多 8 个中文字符（约 160px 宽度）
- 超出自动截断：长文本自动添加"..."省略号
- 所有文本单行显示

### 元素定位规则

- X 坐标范围：60px ≤ x ≤ 740px
- Y 坐标范围：60px ≤ y ≤ 390px
- 元素宽度：自动计算，确保不超出边界
- 居中对齐：以画布中心 400px 为基准
- 大元素优先：主要图形元素占据画面中心位置

### 防溢出技术实现

- 预计算布局：生成前计算所有元素最终位置
- 边界检查函数：每个元素生成后立即验证边界
- 动态调整机制：检测到溢出时自动缩小元素或减少内容
- 零容忍原则：发现任何溢出立即重新调整
- 安全余量：所有计算增加 15px 安全余量

---

## 五、防重叠机制

### 分层布局规则

- 第一层（顶部）：标题区域，占用 y:60-120px
- 第二层（中部）：主要图形区域，占用 y:140-320px
- 第三层（底部）：标签或小元素区域，占用 y:340-390px

### 防重叠措施

- 最小间距：任何两个元素之间必须保持至少 20px 间距
- 元素数量限制：每张图最多 2 个主要元素，避免过度拥挤
- 坐标强制验证：每个元素生成后必须计算边界 box 并检测重叠
- 尺寸自动缩减：检测到潜在重叠时，自动将所有元素缩小 5%
- 优先级规则：标题 > 主图形 > 标签

---

## 六、配图策略

### 核心配图原则

**最重要**：宁可多生成，不要生成太少。

### 配图密度要求

- 目标生成 **10-15 张** 配图（根据文章长度调整）
- 每个重要段落或关键概念生成 1 张配图
- 每个二级标题（##）之后至少配 1 张图

### 配图位置规则

1. 每个二级标题（##）之后立即配图（最高优先级）
2. 文章引言结束后配 1 张图
3. 文章总结/结论之前配 1 张图
4. 重要概念转折、对比、因果关系处配图
5. 每 2-3 个重要段落后配 1 张图

---

## 七、Emoji 使用指南

### Emoji 选择

| 使用场景 | 推荐 emoji | 避免使用 |
|---------|----------|---------|
| 人物角色 | 👨‍💼👩‍💼👨‍⚖️👩‍⚖️👤👥 | 复杂组合 emoji |
| 情感表达 | 😰😫💔✨💪🎯💸🏗️ | 过于小众的 emoji |
| 工具/物品 | 🔧⚖️📋✅❌💡📊 | 含义模糊的 emoji |

### Emoji 使用原则

- 避免复杂组合 emoji（如👨‍👩‍👧‍👦）
- 优先使用常见 emoji
- 控制使用数量：每张图 2-5 个 emoji

---

## 八、布局类型库

| 布局类型 | 适用场景 | 元素数量 | 视觉特点 |
|---------|---------|---------|---------|
| **线性布局** | 流程、步骤、时间线 | 3-5 个 | 简洁清晰，方向性强 |
| **矩阵布局** | 多维对比、分类展示 | 4-9 个 | 结构化强，易于对比 |
| **分层布局** | 层级关系、优先级 | 3-4 层 | 层次分明，上下关系 |
| **环绕布局** | 核心概念 + 相关要素 | 1+4-6 个 | 焦点集中，向心感强 |
| **网状布局** | 复杂关系、相互关联 | 4-6 个 | 关系复杂，网络化 |
| **放射布局** | 从中心发散的概念 | 1+5-8 个 | 扩散感强，动态明显 |

---

## 九、背景色策略

### ⚠️ 背景色选择原则（必读）

背景色是 SVG 配图的 **视觉基底**，必须满足：
1. **非纯白**：禁止使用 `#FFFFFF` 作为画布背景
2. **有区分度**：背景色与内容元素有足够对比度
3. **图级差异化**：同一篇文章内的每张配图使用 **不同背景色**，形成视觉节奏感

### 单图背景色分配规则

同一篇文章内的每张配图使用不同的背景色，通过配图序号分配。

**背景色色库**（按类别分组，便于根据文章主题选择）：

| 类别 | 背景色 | 适用主题 |
|------|--------|----------|
| **中性灰白系** | `#F5F5F5` `#F8F9FA` `#FAFAFA` | 通用、工具指南 |
| **暖白系** | `#FAF8F5` `#FDF8F3` `#FFFBF0` | 生活、文化、随笔 |
| **浅米系** | `#FAF0E6` `#FFF5E6` `#F5E6D3` | 法律、金融、正式 |
| **浅蓝灰系** | `#F0F4F8` `#E8F4F8` `#F0F8FF` | 科技、AI、数据 |
| **浅绿系** | `#E8F5E8` `#F0FFF0` `#E8F8E8` | 成长、教育、环保 |
| **浅粉系** | `#FFF0F5` `#FFE4E8` `#F8E8E8` | 情感、生活方式 |
| **浅紫系** | `#F3E8F8` `#F0E8F8` `#E8E0F0` | 思考、创意、艺术 |
| **浅蓝系** | `#E0F0F8` `#D0E8F5` `#C0E0F0` | 海洋、航空、物理 |
| **浅黄系** | `#FFFBE6` `#FFF8DC` `#FFFFF0` | 阳光、能源、温暖 |

### 分配算法

同一篇文章内的每张配图使用不同的背景色，确保无重复：

```python
# 从色库中依次选择，确保每张图的背景色都不同
colors = ["#F0F4F8", "#FAF8F5", "#E8F5E8", "#F3E8F8", "#FAF0E6", "#FFF0F5", "#E0F0F8", "#FFFBE6"]
# 生成 N 张配图时，选择前 N 个不同的颜色
```

**简化方法**（无需代码）：
- 从色库中依次选择，确保同一篇文章内所有配图的背景色都不同即可

### 边框对比度要求

- 边框色与背景色形成轻微对比（边框色略深于背景色 10-20%）
- 示例：背景 `#F0F4F8` → 边框 `#D0D8E0`
- 示例：背景 `#FAF8F5` → 边框 `#E0D8C8`

---

## 十、兼容性踩坑记录

### 🚫 禁止使用：SVG Filter

**问题描述**：在 SVG 中使用 `<g filter="url(#shadow)">` 添加阴影效果时，SMIL 动画（animateTransform、animate）在微信 WebView 中无法正常显示。

**原因分析**：filter 会在 SVG 中创建一个隔离的渲染层（filter region），与 WeChat WebView 的 SMIL 动画渲染引擎存在兼容性问题。

**错误示例**：
```svg
<g filter="url(#shadow)">
  <rect ...>
    <animateTransform attributeName="transform" type="translate" .../>
  </rect>
</g>
```

**正确做法**：
- ❌ 不要使用 `<g filter="url(#shadow)">` 或任何 filter 效果
- ✅ 使用 `<g transform="translate(x, y)">` 进行定位
- ✅ 动画直接应用在目标元素上，不要被 filter 包裹

**视觉替代方案**：
- 阴影效果 vs 扁平设计 → 选择扁平设计（符合极简原则）
- 如必须体现层次感 → 使用不同颜色区分，而非阴影

---

### ⚠️ 渐变填充 + 动画组合

**问题描述**：当 `fill="url(#gradient)"` 和 `<animateTransform>` 在同一个 `<rect>` 元素上时，渐变在微信 WebView 中无法显示。

**原因分析**：渐变渲染和 SMIL 动画在同一个元素的坐标系中存在冲突。

**错误示例**：
```svg
<!-- ❌ 错误：动画和渐变都在同一个 rect 上 -->
<rect fill="url(#gradient)" ...>
  <animateTransform attributeName="transform" .../>
</rect>
```

**替代方案（推荐）**：
- 直接使用纯色填充，配合极简设计原则
- 如需渐变效果，使用不带动画的静态元素

---

### 🚫 禁止使用：所有渐变填充

**问题描述**：在公众号中，即使是静态的渐变背景也无法渲染。

**原因分析**：公众号 WebView 对 SVG 渐变的支持非常有限，无论是否带动画。

**错误示例**：
```svg
<!-- 背景渐变 -->
<linearGradient id="bgGrad">...</linearGradient>
<rect fill="url(#bgGrad)"/>

<!-- 元素渐变 -->
<linearGradient id="stepGrad">...</linearGradient>
<path fill="url(#stepGrad)"/>
```

**正确做法**：
- 所有渐变都改为纯色
- 背景使用：`#f8f9fa`、`#f0f4f8` 等浅色
- 元素使用对应的主色调纯色

---

## 📋 公众号 SVG 兼容性汇总（实测）

| 测试用例 | 结果 | 说明 |
|---------|------|------|
| 纯色 + 动画 | ✅ 正常 | 测试1、14、15 |
| 虚线流动动画 | ✅ 正常 | 测试5 |
| 箭头绘制动画 | ✅ 正常 | 测试6 |
| Emoji 浮动动画 | ✅ 正常 | 测试9 |
| 脉冲动画 | ✅ 正常 | 测试11 |
| 复杂布局 | ✅ 正常 | 测试13 |
| 渐变背景（无动画） | ❌ 失效 | 测试2、8 |
| 渐变 + 动画（同元素） | ❌ 失效 | 测试3 |
| SVG Filter + 动画 | ❌ 失效 | 测试4 |
| 分离动画和渐变 | ❌ 失效 | 测试10 |
| 纯色 + Filter（无动画） | ❌ 失效 | 测试12 |

**结论**：

| 特性 | 公众号支持 | 备注 |
|------|------------|------|
| 纯色填充 | ✅ 支持 | 推荐使用 |
| SMIL 动画 | ✅ 支持 | 在无 filter/渐变时正常 |
| SVG Filter | ❌ 不支持 | 任何情况都不支持 |
| 渐变填充 | ❌ 不支持 | 任何情况都不支持 |

**最佳实践**：
1. ❌ 禁止使用 `<filter>` 元素
2. ❌ 禁止使用 `<linearGradient>` / `fill="url(#gradient)"`
3. ✅ 所有颜色使用纯色（如 `#10B981`、`#f8f9fa`）
4. ✅ 动画使用 `<animateTransform>` 或 `<animate>`
5. ✅ 元素定位使用 `transform="translate(x, y)"`

---

### 🚨 最高频错误：transform + animateTransform translate 冲突

**问题描述**：当外层使用 `transform="translate(x,y)"` 定位，内层又使用 `<animateTransform type="translate">` 做浮动动画时，**动画会完全覆盖外层的定位**，导致所有元素堆叠到左上角 (0,0)。

**错误示例**：
```svg
<!-- ❌ 错误：translate 定位 + translate 动画 = 元素飞到左上角 -->
<g transform="translate(180, 200)">
  <circle cx="0" cy="0" r="80" fill="#4A90E2"/>
  <animateTransform type="translate" values="0,0; 0,-12; 0,0"/>
</g>
```

**正确做法**：
```svg
<!-- ✅ 正确方法1：直接用 cx/cy 定位，内层包一层做动画 -->
<g>
  <circle cx="180" cy="200" r="80" fill="#4A90E2"/>
  <g>
    <animateTransform type="translate" values="0,0; 0,-12; 0,0"/>
  </g>
</g>

<!-- ✅ 正确方法2：translate 定位 + scale 动画（不冲突） -->
<g transform="translate(180, 200)">
  <circle cx="0" cy="0" r="80" fill="#4A90E2"/>
  <animateTransform type="scale" values="1; 1.1; 1"/>
</g>
```

**核心原则**：
| 定位方式 | 可用动画类型 | 是否安全 |
|---------|------------|---------|
| `transform="translate()"` | `type="scale"` | ✅ 安全 |
| `transform="translate()"` | `type="rotate"` | ✅ 安全 |
| `transform="translate()"` | `type="translate"` | ❌ **禁止！** |
| `cx/cy` 或 `x/y` 直接定位 | `type="translate"` | ✅ 安全 |

**记忆口诀**：translate 定位只能配 scale/rotate，要做浮动必须用 x/y/cx/cy 直接定位！
