# 背面图案渲染 + 大小王素材位置微调 ## 背景 当前背面牌(back)虽有 `'back'` 素材类型的上传 UI,但渲染时完全不使用素材,仅显示纯色 + "CARD BACK" 文字。大小王素材已渲染但无位置微调功能。 ## 需求 ### 1. 背面图案渲染 - 优先从 `project.assets` 中读取 `asset_type='back'` 的素材图片 - 有图时:在躯干区域居中绘制(contain 模式等比适配) - 无图时:保持现有回退(纯色背景 + "CARD BACK" 文字 + 边框) - 支持位置微调 ### 2. 大小王素材位置微调 - 在 DesignPanel 选中大小王时,显示 dx/dy/缩放滑块 - 数据存储在 `card_overrides[joker-key].image_dx, image_dy, image_scale` - `drawJokerBody()` 绘制时应用偏移 ## 数据模型 扩展 `card_overrides` JSON: ```json { "joker-big": { "image_dx": 0, "image_dy": 0, "image_scale": 1 }, "joker-small": { "image_dx": 0, "image_dy": 0, "image_scale": 1 }, "back": { "image_dx": 0, "image_dy": 0, "image_scale": 1 } } ``` - `image_dx` / `image_dy`:相对躯体区域的比例偏移,范围 -0.05 ~ +0.05 - `image_scale`:缩放系数,范围 0.6 ~ 1.4 ## 前端实现 ### cardRenderer.js #### `drawBackSide()` 改动 - 新增 `project` 参数以读取素材和 card_overrides - 调用 `assetByType(project, 'back', 'back')` 获取素材 - 有素材时绘制图片(contain 适配 + 偏移应用) - `renderCard()` 调用处传入 `project` #### `drawJokerBody()` 改动 - 读取 `override = design.image_dx/dy/scale`(由 `getEffectiveDesign()` 合并后传入的 design 包含 card_overrides 字段) - 在图片绘制坐标上叠加 `bodyW * image_dx`、`bodyH * image_dy` - 缩放叠加 `drawW * image_scale`、`drawH * image_scale` ### projectStore.js - 开放 `canHaveOverride` 覆盖 joker 和 back - 添加图片偏移的 patch 方法(复用已有 `patchCardOverride` 或新增) ### DesignPanel.vue - 移除 `canHaveOverride` 对 joker/back 的限制 - 当当前牌为 joker 或 back 时,显示图片位置微调滑块(dx/dy/缩放) ## 后端实现 ### exports/utils.py #### `generate_card_png()` back 分支 - 查找 `project.assets.filter(asset_type='back')` 获取素材 - `load_image_safe()` 加载图片 - `draw_back()` 函数中用 `thumbnail` contain 适配 + 偏移 #### `draw_joker()` 改动 - 读取 `card_overrides` 的 image_dx/dy/scale - 在坐标计算中叠加偏移和缩放 ## UI 滑块参数 - dx: range -0.05 ~ +0.05, step 0.005 - dy: range -0.05 ~ +0.05, step 0.005 - scale: range 0.6 ~ 1.4, step 0.05 (与现有 number_layout 一致)