TravelContentCreator/docs/POSTER_FABRIC_PLAN.md
jinye_huang fa6b5967f5 docs: 海报 Fabric.js 前端渲染方案
- 新增 POSTER_FABRIC_PLAN.md 方案文档
- 双输出设计: preview_base64 (快速预览) + fabric_json (前端编辑)
- 复用现有 AI 文案生成逻辑
- 三阶段实施计划
2025-12-10 15:38:55 +08:00

348 lines
8.6 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.

# 海报生成方案 - Fabric.js 前端渲染
## 背景
当前方案在 Python 端下载图片并渲染海报,存在以下问题:
- 图片下载耗时长
- 输出静态 PNG用户无法编辑
- 服务端渲染压力大
## 新方案概述
**Python 端只生成文案和布局参数,输出 fabric.js JSON前端负责渲染和合成。**
```
┌─────────────┐ JSON ┌─────────────┐ Canvas ┌─────────────┐
│ Python AI │ ─────────▶ │ Frontend │ ──────────▶ │ 用户编辑 │
│ 文案生成 │ │ fabric.js │ │ 导出图片 │
└─────────────┘ └─────────────┘ └─────────────┘
```
## 数据流
### 1. 输入 (用户请求)
```json
{
"category": "民宿",
"name": "山舍云端民宿",
"description": "藏在莫干山的治愈系民宿",
"price": "458元/晚",
"location": "莫干山",
"features": "独立庭院, 手冲咖啡, 山景露台",
"image_url": "https://example.com/image.jpg"
}
```
### 2. Python 输出 (Fabric.js JSON)
```json
{
"version": "1.0.0",
"canvas": {
"width": 1080,
"height": 1440,
"backgroundColor": "#FFF5F0"
},
"layout": "hero_bottom",
"theme": "sunset",
"content": {
"title": "去了莫干山才知道...",
"subtitle": "藏在山里的治愈系民宿,推开窗便是云海",
"highlights": ["独立庭院", "手冲咖啡", "山景露台"],
"details": ["管家式服务超贴心", "有机早餐太惊艳"],
"price": "¥458",
"price_suffix": "/晚",
"tags": ["莫干山民宿", "周末度假"]
},
"objects": [
{
"id": "background_image",
"type": "image",
"src": "https://example.com/image.jpg",
"left": 0,
"top": 0,
"width": 1080,
"height": 1440,
"scaleX": 1,
"scaleY": 1
},
{
"id": "gradient_overlay",
"type": "rect",
"left": 0,
"top": 800,
"width": 1080,
"height": 640,
"fill": {
"type": "linear",
"coords": {"x1": 0, "y1": 0, "x2": 0, "y2": 640},
"colorStops": [
{"offset": 0, "color": "rgba(89,66,52,0)"},
{"offset": 0.5, "color": "rgba(89,66,52,0.8)"},
{"offset": 1, "color": "rgba(89,66,52,1)"}
]
}
},
{
"id": "title",
"type": "textbox",
"text": "去了莫干山才知道...",
"left": 48,
"top": 880,
"width": 984,
"fontSize": 80,
"fontFamily": "PingFang SC",
"fontWeight": "bold",
"fill": "#FFFFFF",
"shadow": "rgba(0,0,0,0.3) 2px 2px 4px"
},
{
"id": "subtitle",
"type": "textbox",
"text": "藏在山里的治愈系民宿,推开窗便是云海",
"left": 48,
"top": 980,
"width": 984,
"fontSize": 32,
"fontFamily": "PingFang SC",
"fill": "rgba(255,255,255,0.85)"
},
{
"id": "price_bg",
"type": "rect",
"left": 36,
"top": 1280,
"width": 180,
"height": 60,
"rx": 12,
"ry": 12,
"fill": "rgba(255,255,255,0.2)"
},
{
"id": "price",
"type": "text",
"text": "¥458",
"left": 48,
"top": 1290,
"fontSize": 48,
"fontFamily": "PingFang SC",
"fontWeight": "bold",
"fill": "#FFFFFF"
},
{
"id": "price_suffix",
"type": "text",
"text": "/晚",
"left": 160,
"top": 1308,
"fontSize": 24,
"fontFamily": "PingFang SC",
"fill": "rgba(255,255,255,0.8)"
}
]
}
```
## 架构设计
### Python 端
```
domain/aigc/engines/
├── poster_smart_v1.py # 当前AI文案 + Python渲染
└── poster_smart_v2.py # 新增AI文案 + Fabric JSON输出
```
#### PosterSmartEngineV2 职责
1. **AI 文案生成** - 调用 LLM 生成标题、副标题、亮点等
2. **布局推荐** - 根据内容类型推荐布局
3. **主题推荐** - 根据内容类型推荐配色
4. **Fabric JSON 生成** - 输出标准 fabric.js 格式
```python
class PosterSmartEngineV2(BaseEngine):
"""智能海报引擎 V2 - 输出 Fabric.js JSON"""
async def execute(self, params: dict) -> EngineResult:
# 1. AI 生成文案
content = await self._generate_content(params)
# 2. 选择布局和主题
layout = content.get('suggested_layout') or self._recommend_layout(params)
theme = content.get('suggested_theme') or self._recommend_theme(params)
# 3. 生成 Fabric JSON
fabric_json = self._generate_fabric_json(content, layout, theme, params)
return EngineResult(
success=True,
data={
'fabric_json': fabric_json,
'layout': layout,
'theme': theme,
'content': content
}
)
```
### 前端
```
components/
├── PosterEditor/
│ ├── index.tsx # 主组件
│ ├── FabricCanvas.tsx # fabric.js 画布
│ ├── LayerPanel.tsx # 图层面板
│ ├── PropertyPanel.tsx # 属性面板
│ └── ExportButton.tsx # 导出按钮
```
#### 前端职责
1. **加载 Fabric JSON** - 解析 Python 返回的 JSON
2. **渲染画布** - fabric.js 渲染所有对象
3. **用户编辑** - 支持移动、缩放、修改文字
4. **导出图片** - 导出 PNG/JPG
## 布局模板
### 5 种布局的 Fabric 结构
| 布局 | 结构 |
|-----|------|
| **hero_bottom** | 图片全屏 + 底部渐变 + 文字叠加 |
| **overlay_center** | 图片全屏 + 暗化遮罩 + 居中文字 |
| **overlay_bottom** | 图片上半 + 毛玻璃卡片底部 |
| **split_vertical** | 左侧渐变/图片 + 右侧文字 |
| **card_float** | 图片全屏 + 悬浮白色卡片 |
### 布局模板文件
```
poster_v2/templates/
├── hero_bottom.json
├── overlay_center.json
├── overlay_bottom.json
├── split_vertical.json
└── card_float.json
```
## 主题配置
```python
THEMES = {
"sunset": {
"primary": "#594234",
"secondary": "#FFF5F0",
"accent": "#D4A574",
"text": "#FFFFFF",
"text_dark": "#333333",
"gradient": ["#FFE4D6", "#D4A574"]
},
# ... 其他主题
}
```
## API 设计
### 请求
```http
POST /api/v2/aigc/execute
Content-Type: application/json
{
"engine": "poster_smart_v2",
"params": {
"category": "民宿",
"name": "山舍云端民宿",
"description": "藏在莫干山的治愈系民宿",
"price": "458元/晚",
"image_url": "https://example.com/image.jpg"
}
}
```
### 响应 (双输出)
```json
{
"success": true,
"data": {
"preview_base64": "data:image/png;base64,...",
"fabric_json": {
"version": "1.0.0",
"canvas": { "width": 1080, "height": 1440 },
"objects": [...]
},
"layout": "hero_bottom",
"theme": "sunset",
"content": {
"title": "去了莫干山才知道...",
"subtitle": "...",
"highlights": [...],
"price": "¥458"
}
}
}
```
### 输出说明
| 字段 | 说明 |
|-----|------|
| `preview_base64` | **预览 PNG** - 无底图,使用主题渐变色背景,快速预览文案排版 |
| `fabric_json` | **Fabric JSON** - 完整的编辑数据,含图片占位,前端加载后可编辑 |
| `layout` | 推荐布局 |
| `theme` | 推荐主题 |
| `content` | AI 生成的文案内容 |
## 实现步骤
### Phase 1: Python 端 (2-3天)
1. [ ] 创建 `poster_smart_v2.py` 引擎
2. [ ] 实现 5 种布局的 Fabric JSON 生成器
3. [ ] 复用现有的 AI 文案生成逻辑
4. [ ] 添加 API 路由
### Phase 2: 前端 (3-5天)
1. [ ] 集成 fabric.js
2. [ ] 实现 FabricCanvas 组件
3. [ ] 实现图层面板
4. [ ] 实现属性编辑
5. [ ] 实现导出功能
### Phase 3: 优化 (1-2天)
1. [ ] 字体加载优化
2. [ ] 图片懒加载
3. [ ] 撤销/重做
4. [ ] 模板保存
## 兼容性
- 保留 `poster_smart_v1` 引擎,支持服务端渲染
- 新增 `poster_smart_v2` 引擎,支持 Fabric JSON 输出
- 前端根据需求选择调用哪个引擎
## 优势
| 方面 | 收益 |
|-----|------|
| **性能** | 服务端不再处理图片,响应更快 |
| **可编辑** | 用户可自由调整文字、位置、颜色 |
| **灵活性** | 前端可扩展更多编辑功能 |
| **复用性** | Fabric JSON 可保存为模板复用 |
## 风险与对策
| 风险 | 对策 |
|-----|------|
| 字体不一致 | 前端加载相同字体文件 |
| 跨域图片 | 配置 CORS 或使用代理 |
| 复杂效果 | 渐变、阴影用 fabric.js 内置功能 |