TravelContentCreator/docs/VIBRANT_TEMPLATE_ANALYSIS.md
jinye_huang dcfd820ca4 feat(poster_v2): 智能海报生成引擎 v1.0
- 新增 PosterSmartEngine,AI 生成文案 + 海报渲染
- 5 种布局支持文本换行和自适应字体
- 修复按钮/标签颜色显示问题
- 优化渐变遮罩和内容区域计算
- Prompt 优化:标题格式为产品名+描述
2025-12-10 15:04:59 +08:00

473 lines
12 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.

# 海报系统设计思考
> 基于 `poster/templates/vibrant_template.py` 分析
> 创建日期: 2024-12-10
---
## 核心问题
**如何批量生成视觉美观的海报模板?**
技术实现(槽位、元素、渲染)相对简单,真正的挑战是:
- 什么样的布局是"好看"的?
- 如何系统化地产出大量"好看"的模板?
- 有没有可复用的设计规则?
---
## 一、美观的本质
### 1.1 设计的基本原则
| 原则 | 说明 | 海报中的体现 |
|-----|------|-------------|
| **对比** | 差异产生层次 | 大标题 vs 小说明 |
| **对齐** | 视觉秩序感 | 元素沿网格排列 |
| **重复** | 一致性、统一感 | 相同字体、颜色体系 |
| **亲密** | 相关元素靠近 | 价格和票种紧挨 |
| **留白** | 呼吸感、焦点突出 | 不塞满每个角落 |
| **层次** | 引导视觉流动 | 标题→副标题→详情 |
### 1.2 海报的视觉结构
```
┌─────────────────────────────────────┐
│ │
│ 视觉焦点区 (Hero) │ ← 图片/主视觉
│ 占据 50-70% │
│ │
├─────────────────────────────────────┤
│ 核心信息区 (Core) │ ← 标题、价格
│ 占据 20-30% │
│ │
├─────────────────────────────────────┤
│ 辅助信息区 (Support) │ ← 详情、备注
│ 占据 10-20% │
└─────────────────────────────────────┘
```
### 1.3 为什么有些海报好看?
**好看的共性**
1. **焦点明确** - 一眼知道看什么
2. **层次清晰** - 信息有主次
3. **色彩和谐** - 不超过 3 种主色
4. **留白充足** - 不拥挤
5. **字体克制** - 不超过 2 种字体
**难看的共性**
1. 信息堆砌,没有重点
2. 颜色杂乱,互相打架
3. 字体大小差异不够,层次模糊
4. 填满每一寸空间
---
## 二、批量生成美观模板的思路
### 2.1 思路对比
| 思路 | 描述 | 优点 | 缺点 |
|-----|------|------|------|
| **A: 人工设计** | 设计师逐个制作 | 质量高 | 成本高、数量有限 |
| **B: 参数变体** | 一个模板 + 参数变化 | 快速 | 同质化严重 |
| **C: 设计规则** | 定义规则,组合生成 | 可扩展 | 规则难以穷尽"美" |
| **D: AI 生成** | 用 AI 生成布局/配色 | 潜力大 | 质量不稳定 |
| **E: 混合方案** | 规则约束 + 设计资产库 | 平衡 | 需要前期投入 |
**建议: 方案 E - 设计规则 + 资产库**
### 2.2 设计资产库思路
```
美观模板 = 布局骨架 × 配色方案 × 字体组合 × 装饰元素
```
**布局骨架** (Layouts):
```yaml
layouts:
hero_bottom: # 大图在上,文字在下
image: [0, 0, 100%, 60%]
content: [0, 55%, 100%, 45%]
hero_left: # 大图在左,文字在右
image: [0, 0, 50%, 100%]
content: [50%, 0, 50%, 100%]
hero_center: # 文字叠加在图片中央
image: [0, 0, 100%, 100%]
content: [10%, 30%, 80%, 40%]
split_horizontal: # 上下分割
top: [0, 0, 100%, 50%]
bottom: [0, 50%, 100%, 50%]
card_style: # 卡片式,有边框和圆角
margin: 5%
border_radius: 20
shadow: true
```
**配色方案** (Color Schemes):
```yaml
color_schemes:
ocean:
primary: "#1a5f7a"
secondary: "#57c5b6"
accent: "#ffc107"
text: "#ffffff"
sunset:
primary: "#ff6b6b"
secondary: "#feca57"
accent: "#ffffff"
text: "#2d3436"
forest:
primary: "#2d5a27"
secondary: "#8bc34a"
accent: "#ffeb3b"
text: "#ffffff"
minimal:
primary: "#212121"
secondary: "#757575"
accent: "#ff5722"
text: "#ffffff"
pastel:
primary: "#a8d8ea"
secondary: "#aa96da"
accent: "#fcbad3"
text: "#2d3436"
```
**字体组合** (Font Pairs):
```yaml
font_pairs:
modern:
title: "阿里巴巴普惠体-Bold"
body: "思源黑体-Regular"
elegant:
title: "方正清刻本悦宋"
body: "思源宋体-Light"
playful:
title: "站酷快乐体"
body: "思源黑体-Regular"
business:
title: "兰亭黑-Heavy"
body: "兰亭黑-Light"
```
**装饰元素** (Decorations):
```yaml
decorations:
none: {}
line_divider:
type: line
position: below_title
width: 60%
gradient_overlay:
type: gradient
direction: bottom_up
opacity: 0.7
corner_badge:
type: badge
position: top_right
style: ribbon
bottom_wave:
type: shape
path: wave
position: bottom
```
### 2.3 组合生成
```
5 布局 × 10 配色 × 4 字体组合 × 5 装饰 = 1000 种组合
```
但不是所有组合都好看,需要:
1. **兼容性规则** - 哪些组合是合理的
2. **质量过滤** - 排除明显不好的组合
3. **人工精选** - 从中挑选最佳组合
### 2.4 兼容性矩阵
```yaml
compatibility:
# 布局 vs 配色
hero_bottom:
good_with: [ocean, sunset, forest] # 需要鲜明色彩
avoid: [minimal] # 太素会显空
hero_center:
good_with: [minimal, pastel] # 需要低对比度
avoid: [sunset] # 太强会干扰文字
# 字体 vs 场景
playful:
good_for: [亲子, 美食, 娱乐]
avoid_for: [商务, 地产, 金融]
elegant:
good_for: [酒店, 文化, 艺术]
avoid_for: [促销, 快消]
```
---
## 三、实用的模板生成策略
### 3.1 场景驱动
不要从"布局"出发,而是从**使用场景**出发:
```yaml
scenarios:
景点门票:
typical_content: [景点名, 价格, 票种, 有效期, 注意事项]
visual_style: 活力、明亮
recommended_layouts: [hero_bottom, hero_center]
recommended_colors: [ocean, sunset, forest]
酒店住宿:
typical_content: [酒店名, 房型, 价格, 设施, 地址]
visual_style: 优雅、高端
recommended_layouts: [hero_bottom, card_style]
recommended_colors: [minimal, pastel]
美食推荐:
typical_content: [店名, 招牌菜, 价格, 地址, 营业时间]
visual_style: 温暖、诱人
recommended_layouts: [hero_center, split_horizontal]
recommended_colors: [sunset, pastel]
促销活动:
typical_content: [活动名, 原价, 现价, 时间, 规则]
visual_style: 醒目、紧迫感
recommended_layouts: [hero_bottom]
recommended_colors: [sunset]
decorations: [corner_badge]
```
### 3.2 变体生成策略
从一个"基准模板"生成变体:
```
基准模板 (人工精调)
├─ 配色变体 (换色不换布局)
│ ├─ ocean 版
│ ├─ sunset 版
│ └─ forest 版
├─ 布局变体 (换布局不换风格)
│ ├─ 文字在下
│ ├─ 文字在右
│ └─ 文字叠加
└─ 密度变体 (同布局不同内容量)
├─ minimal 版 (只有标题+价格)
├─ standard 版 (标题+价格+列表)
└─ full 版 (所有信息)
```
### 3.3 设计约束(保底美观)
```yaml
constraints:
# 比例约束
title_to_body_ratio: [2, 4] # 标题是正文的 2-4 倍大
image_min_ratio: 0.4 # 图片至少占 40%
content_max_ratio: 0.5 # 文字最多占 50%
# 间距约束
min_margin: 5% # 最小边距
element_gap: 15-30px # 元素间距
# 颜色约束
max_colors: 3 # 最多 3 种主色
contrast_ratio: 4.5 # 文字对比度 (可读性)
# 字体约束
max_font_families: 2 # 最多 2 种字体
min_font_size: 14px # 最小字号
# 信息层级
levels:
- name: hero # 最突出
size: 60-150px
count: 1
- name: primary # 主要
size: 30-60px
count: 1-2
- name: secondary # 次要
size: 16-30px
count: 0-5
- name: tertiary # 辅助
size: 12-16px
count: 0-3
```
---
## 四、落地方案
### 4.1 短期:精选模板库
```
第一步:人工设计 10-20 个高质量基准模板
第二步:每个模板生成 3-5 个配色变体
第三步:形成 50-100 个可用模板
```
### 4.2 中期:规则化生成
```
第一步:抽象出布局骨架库 (5-10 种)
第二步:抽象出配色方案库 (10-20 种)
第三步:定义兼容性规则
第四步:自动组合 + 人工筛选
```
### 4.3 长期AI 辅助
```
第一步:收集优秀海报数据集
第二步:训练/使用 AI 生成布局建议
第三步AI 配色推荐
第四步:人工微调 + 质量把控
```
---
## 五、参考:业界做法
### Canva
- 10000+ 模板,人工设计为主
- 强调"替换即用",用户改图片和文字
- 模板按场景分类
### 稿定设计
- 模板 + 智能抠图
- 风格迁移(把 A 风格应用到 B 内容)
### 美图秀秀
- 模板 + AI 排版建议
- 根据图片内容推荐布局
### 关键启示
1. **模板数量很重要** - 用户需要选择
2. **场景分类很重要** - 快速找到合适的
3. **可定制性很重要** - 改颜色、改内容
4. **质量比数量重要** - 宁可少但精
---
## 六、下一步行动建议
### 优先级 1: 建立设计资产库
- [ ] 定义 5 种核心布局骨架
- [ ] 定义 10 种配色方案
- [ ] 定义 3-4 种字体组合
- [ ] 建立兼容性规则
### 优先级 2: 人工精调基准模板
- [ ] 针对"景点门票"场景,设计 3 个高质量模板
- [ ] 验证模板在不同内容下的表现
- [ ] 生成配色变体
### 优先级 3: 实现模板引擎
- [ ] 支持从 YAML 加载模板配置
- [ ] 支持动态切换配色
- [ ] 支持内容自适应
---
## 附录VibrantTemplate 技术参考
以下是现有 `vibrant_template.py` 的技术细节,供重构参考。
### A.1 入口方法
```python
generate(images, content, theme_color, glass_intensity, num_variations, **kwargs)
```
**流程**:
1. 判断是否需要生成 Fabric.js JSON
2. 如果需要 → `_unified_render()` (PNG + JSON)
3. 否则 → `_generate_legacy()` (仅 PNG)
### A.2 核心功能模块
| 模块 | 方法 | 职责 |
|-----|------|------|
| **图片处理** | `resize_image` | 调整图片到目标尺寸 |
| **渐变检测** | `_detect_gradient_start_position` | 智能检测毛玻璃起始位置 |
| **颜色提取** | `_extract_glass_colors_from_image` | 从图片提取毛玻璃颜色 |
| **毛玻璃效果** | `_create_frosted_glass_overlay` | 创建渐变半透明覆盖层 |
| **布局计算** | `_calculate_content_margins` | 计算内容区域边距 |
| **字体自适应** | `_calculate_optimal_font_size_enhanced` | 二分查找最佳字体大小 |
| **文字渲染** | `_render_texts` | 渲染所有文本元素 |
| **PSD 生成** | `generate_layered_psd` | 生成分层 PSD 文件 |
### A.3 内容数据结构
```python
content = {
"title": "正佳极地海洋世界", # 必选
"slogan": "都说海洋馆是约会圣地!", # 重要
"price": "199", # 必选
"ticket_type": "夜场票", # 重要
"content_button": "套餐内容",
"content_items": ["项目1", "项目2"], # 重要
"remarks": ["备注1", "备注2"], # 可选
"tag": "#520特惠", # 可选
"pagination": "1/3" # 可选
}
```
### A.4 问题清单
| 问题 | 说明 |
|-----|------|
| 文件过大 | 1757 行 |
| 重复代码 | `_create_text_only_layer` 定义两次 |
| 硬编码参数 | 字体路径、位置像素值 |
| 职责混杂 | 布局、渲染、特效混在一起 |
### A.5 渲染流程
```
generate() → _generate_legacy()
├─ resize_image()
├─ _detect_gradient_start_position()
├─ _create_composite_image()
│ └─ _create_frosted_glass_overlay()
└─ _render_texts()
├─ _render_title_subtitle()
├─ _render_left_column()
├─ _render_right_column()
└─ _render_footer()
```