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

8.6 KiB
Raw Blame History

海报生成方案 - Fabric.js 前端渲染

背景

当前方案在 Python 端下载图片并渲染海报,存在以下问题:

  • 图片下载耗时长
  • 输出静态 PNG用户无法编辑
  • 服务端渲染压力大

新方案概述

Python 端只生成文案和布局参数,输出 fabric.js JSON前端负责渲染和合成。

┌─────────────┐    JSON     ┌─────────────┐    Canvas    ┌─────────────┐
│  Python AI  │ ─────────▶  │  Frontend   │ ──────────▶  │   用户编辑   │
│  文案生成    │             │  fabric.js  │              │   导出图片   │
└─────────────┘             └─────────────┘              └─────────────┘

数据流

1. 输入 (用户请求)

{
  "category": "民宿",
  "name": "山舍云端民宿",
  "description": "藏在莫干山的治愈系民宿",
  "price": "458元/晚",
  "location": "莫干山",
  "features": "独立庭院, 手冲咖啡, 山景露台",
  "image_url": "https://example.com/image.jpg"
}

2. Python 输出 (Fabric.js 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 格式
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

主题配置

THEMES = {
    "sunset": {
        "primary": "#594234",
        "secondary": "#FFF5F0",
        "accent": "#D4A574",
        "text": "#FFFFFF",
        "text_dark": "#333333",
        "gradient": ["#FFE4D6", "#D4A574"]
    },
    # ... 其他主题
}

API 设计

请求

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"
  }
}

响应 (双输出)

{
  "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 内置功能