docs: 海报 Fabric.js 前端渲染方案
- 新增 POSTER_FABRIC_PLAN.md 方案文档 - 双输出设计: preview_base64 (快速预览) + fabric_json (前端编辑) - 复用现有 AI 文案生成逻辑 - 三阶段实施计划
This commit is contained in:
parent
f96f0257ab
commit
fa6b5967f5
347
docs/POSTER_FABRIC_PLAN.md
Normal file
347
docs/POSTER_FABRIC_PLAN.md
Normal file
@ -0,0 +1,347 @@
|
||||
# 海报生成方案 - 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 内置功能 |
|
||||
Loading…
x
Reference in New Issue
Block a user