# 海报系统设计思考 > 基于 `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() ```