229 lines
11 KiB
Markdown
229 lines
11 KiB
Markdown
# 奇幻酒馆 UI 开发经验沉淀
|
||
|
||
## 1. 总体原则
|
||
|
||
### 1.1 先保证移动端成立,再兼容网页端
|
||
- 入口页、世界选择、角色选择、冒险页、弹窗面板,都要先按手机竖屏去定义信息密度。
|
||
- 网页端只做“放宽容器、增加留白、补充 hover”,不要反过来让桌面布局压垮手机体验。
|
||
- 任何区域如果在移动端需要滚动,必须明确谁滚动,不能让整页和局部同时争夺滚动。
|
||
|
||
### 1.2 游戏 UI 要优先“状态清晰”,而不是“文案很多”
|
||
- 开始页应该像主菜单,不像产品介绍页。
|
||
- 角色选择页应该像角色选择器,不像角色说明书。
|
||
- 冒险页应该像战斗/剧情操作台,不像文档阅读器。
|
||
|
||
### 1.3 一屏内的层级顺序要稳定
|
||
- 上半部分:画面演出。
|
||
- 中间部分:剧情或核心信息。
|
||
- 底部:操作按钮。
|
||
- 玩家必须能快速判断“我在看什么、下一步点哪里”。
|
||
|
||
## 2. 入口页经验
|
||
|
||
### 2.1 开始页
|
||
- 极简化是对的。
|
||
- 当前实践证明:开始页只保留“开始游戏”和“开发团队”两个主按钮,体验明显更像游戏。
|
||
- 游戏名和英文副标题可以保留,但不要再加长段描述。
|
||
|
||
### 2.2 世界选择
|
||
- 纵向焦点轮播比普通列表更适合移动端。
|
||
- 当前居中的卡片应该最大、最清晰、最亮;上下卡片缩放和透明度随滚动连续变化。
|
||
- 世界确认动作应该绑定当前聚焦卡,而不是每张卡都塞太多按钮。
|
||
|
||
### 2.3 角色选择
|
||
- 横向轮播是正确方向。
|
||
- 中间卡片应承担“主视觉 + 主要信息”。
|
||
- 左右卡片只做预览,不需要承载完整信息。
|
||
- 左右卡片倾斜方向一定要符合透视直觉:
|
||
左侧卡片向左外倾,右侧卡片向右外倾。
|
||
- 中间卡片不要出现任何模糊,否则会破坏“当前选中”的确认感。
|
||
|
||
## 3. 角色选择页经验
|
||
|
||
### 3.1 聚焦卡的表现
|
||
- 中间聚焦卡用角色 `run` 动画是有效的,能明显提升“角色活着”的感觉。
|
||
- 但动画资源和静态立绘的锚点通常不一致,必须单独做位置与缩放修正。
|
||
- 结论:
|
||
动画版角色不要直接复用静态图样式,要单独给 `transform`、`height`、`transform-origin`。
|
||
|
||
### 3.2 信息区要紧凑
|
||
- 角色数值和角色背景应该放在轮播下方,但必须压缩高度。
|
||
- 如果下方面板过高,会直接破坏上半部分轮播体验,尤其在手机上。
|
||
- 删除背景面板里的额外动画模块是正确的,因为它与主轮播重复抢视觉焦点。
|
||
|
||
### 3.3 文案层级
|
||
- 页面标题只保留一句:
|
||
“选择你扮演的角色”
|
||
- 不要再强调 `CHARACTER SELECT` 之类的开发向分类标签。
|
||
- 聚焦卡下方直接显示角色名,比把名字只放在卡片底部更直观。
|
||
|
||
### 3.4 按钮位置
|
||
- “确认选择”必须放在角色轮播和信息区之后,作为页面最后的主动作。
|
||
- 按钮不宜过宽过高,否则会抢轮播的视觉重心。
|
||
|
||
## 4. 冒险页经验
|
||
|
||
### 4.1 剧情区必须自适应
|
||
- 剧情文本区不应该写死高度。
|
||
- 正确做法是:
|
||
让它自动填满“上方画面下缘”和“底部按钮区上缘”之间的剩余空间。
|
||
- 这样才能同时保证:
|
||
1. 上方画面一屏可见
|
||
2. 下方三个选项一屏可见
|
||
3. 中间剧情尽量大
|
||
|
||
### 4.2 底部操作区必须锚定到底
|
||
- 队伍、背包、换一换、选项列表,都应该属于底部控制区。
|
||
- 用户会天然在屏幕底部寻找交互入口,尤其是手机。
|
||
- 因此:
|
||
不要把这些按钮漂在中间,不要让剧情区把它们挤走。
|
||
|
||
### 4.3 队伍与背包不应打断主流程
|
||
- 在冒险页内,队伍和背包更适合“弹出面板”而不是“切换整页”。
|
||
- 原因:
|
||
1. 不会打断当前剧情阅读
|
||
2. 用户返回成本更低
|
||
3. 操作像手游副面板,更符合预期
|
||
|
||
### 4.3.1 弹出确认面板不能透明
|
||
- 删除作品、发布后分享、确认离开等关键弹窗必须有实体面板底色,不能只靠透明背景、毛玻璃或遮罩承载内容。
|
||
- 通过 portal 挂到 `body` 的平台弹窗必须在遮罩层补齐平台主题类,否则主题变量会脱离页面容器,轻则颜色漂移,重则面板背景看起来透明。
|
||
- 移动端关键确认弹窗优先居中显示,并保留 `max-height + 内部滚动`,避免被底部导航、安全区或底部抽屉布局遮住。
|
||
|
||
### 4.4 图标优于文字按钮
|
||
- 在底部工具区,队伍/背包改成 icon 后更紧凑。
|
||
- 但必须保留 `aria-label`,保证语义清晰、后续也方便测试。
|
||
|
||
### 4.5 冒险主场景不要挂右上角账号悬浮条
|
||
- 冒险页右上角属于画面演出和战斗/剧情信息的高频观察区。
|
||
- 全局账号信息条挂在这里,会直接压住场景、敌人血条或顶部提示,手机端尤其明显。
|
||
- 结论:
|
||
账号入口应收回平台首页、个人页或设置面板,不要在实际冒险主场景常驻悬浮显示。
|
||
- 当前仓库已进一步收口为:
|
||
不再提供右上角全局账号悬浮条,统一只保留页面内入口与独立账号面板。
|
||
|
||
### 4.6 冒险主场景双方角色必须按画面中线镜像
|
||
- 非滚动画面的交谈、预览、单体对峙态,主角和对面角色不能分别用左右边距、世界坐标和角色宽度重复推算。
|
||
- 正确做法是先定义“角色容器中心距离画面中线”的统一间距,再让主角中心落在中线左侧、对面角色中心落在中线右侧。
|
||
- 角色容器宽度、角色图片缩放和左右朝向必须各自独立处理,不能用额外 left inset 去修正角色图片,否则会破坏左右对称。
|
||
- 自定义图片 NPC、模板角色和组合式 NPC 都要进入同一 112px 场景容器,再按各自素材锚点做场景缩放,保证视觉大小不漂移。
|
||
|
||
## 5. 队伍面板经验
|
||
|
||
### 5.1 移动端成员列表不能太“卡片化”
|
||
- 如果每个成员都再套一层大边框卡片,手机上会显得很挤。
|
||
- 更好的方式是直接在主面板里陈列成员,弱化分隔、强化内容。
|
||
|
||
### 5.2 队伍列表展示什么
|
||
- 头像
|
||
- 姓名
|
||
- 称号
|
||
- 身份标记(领队/同行)
|
||
- HP / MP
|
||
|
||
### 5.3 队伍详情弹窗
|
||
- 弹窗必须可滚动。
|
||
- 弹窗宽度不宜太大,手机优先单列或偏单列。
|
||
- 技能、装备、属性三个区块保持稳定结构,便于扫读。
|
||
|
||
## 6. 背包页经验
|
||
|
||
### 6.1 格子数要优先适配手机
|
||
- 手机端格子间距要小一号。
|
||
- 图标尺寸和分类角标要跟着缩小。
|
||
- 目标不是“每个格子信息很多”,而是“单屏能看更多格子”。
|
||
|
||
### 6.2 背包详情弹窗
|
||
- 手机端改成单列/窄宽度布局更合理。
|
||
- 详情窗里的信息顺序建议固定:
|
||
1. 名称与类别
|
||
2. 品质与数量
|
||
3. 大图标
|
||
4. 说明
|
||
5. 标签
|
||
|
||
## 7. 样式与动画经验
|
||
|
||
### 7.1 轮播动画要连续,不要离散
|
||
- 滚动时应根据“当前位置与当前卡片中心的距离”实时计算:
|
||
- `scale`
|
||
- `opacity`
|
||
- `rotate`
|
||
- `translate`
|
||
- 不要做成“翻页后才跳变”的效果。
|
||
|
||
### 7.2 焦点卡与非焦点卡的职责要不同
|
||
- 焦点卡负责可读性与确认感。
|
||
- 非焦点卡负责预告与空间深度。
|
||
- 所以焦点卡不该模糊,非焦点卡可以轻微降透明度、缩放、偏移。
|
||
|
||
### 7.3 资源锚点要单独校准
|
||
- 静态立绘和动画帧经常不是同一锚点。
|
||
- 只要切换成动画,就需要重新调:
|
||
- 高度
|
||
- Y 偏移
|
||
- 缩放
|
||
- `transform-origin`
|
||
|
||
## 8. 工程经验
|
||
|
||
### 8.1 组件要继续拆
|
||
- 本轮重构证明,把入口页、冒险页、队伍页、背包页拆成独立组件是正确的。
|
||
- 后续新增 UI 需求时,应优先落在:
|
||
- `GameShell.tsx`
|
||
- `AdventurePanel.tsx`
|
||
- `CharacterPanel.tsx`
|
||
- `InventoryPanel.tsx`
|
||
|
||
### 8.2 不要相信“服务已经在跑”
|
||
- 这轮出现过“端口上有进程,但浏览器仍然拿到旧模块”的问题。
|
||
- 实际经验:
|
||
1. 要检查 `src` 文件内容
|
||
2. 要检查 dev server 实际返回的模块内容
|
||
3. 要确认启动脚本是否是当前项目真正使用的脚本
|
||
|
||
### 8.3 本项目当前开发服务入口
|
||
- 本地正确启动脚本是:
|
||
`node scripts/vite-cli.mjs --port=3000 --host=0.0.0.0`
|
||
- 历史脚本或旧进程会导致“代码已改但 UI 看起来没变”的假象。
|
||
|
||
## 9. 后续建议
|
||
|
||
### 9.1 可以继续统一中英混杂文案
|
||
- 当前部分新旧文本仍有历史遗留字符问题。
|
||
- 如果后面继续做 UI 精修,建议单独做一轮文案清洗。
|
||
|
||
### 9.2 可以把轮播抽成通用组件
|
||
- 世界纵向焦点轮播
|
||
- 角色横向倾斜轮播
|
||
- 这两套逻辑已经足够稳定,适合后续抽成通用 hook 或通用组件。
|
||
|
||
### 9.3 可以补移动端安全区适配
|
||
- 当前已经偏移动端优先,但还可以继续加:
|
||
- `safe-area-inset-bottom`
|
||
- `safe-area-inset-top`
|
||
- 更细的竖屏断点处理
|
||
|
||
## 10. 一句话结论
|
||
|
||
这一轮最关键的经验是:
|
||
**游戏 UI 的移动端优化,本质不是把元素缩小,而是重组视觉重心、固定操作锚点、让焦点内容在一屏内自然成立。**
|
||
|
||
### 10.1 可扮演角色形象预览保持 1:1
|
||
- 可扮演角色的形象预览容器统一使用 1:1 方形,入口选择轮播、角色资产工坊和结果页角色卡片都不能用纵向长卡片去拉伸预览图。
|
||
- 预览图片本身使用 `object-contain`,保证 AI 生成主形象、模板像素角色和运行时动画都在方形容器内完整显示,不裁切角色主体。
|
||
- 卡片可以在方形预览下方放角色名、称号、状态等信息,但这些文本区不能反向影响预览区比例。
|
||
- 编辑角色弹窗也遵循同一规则:移动端不能用固定高度压扁预览区,预览容器应随宽度保持 `aspect-square`。
|
||
|
||
### 10.2 运行画面怪物锚点按视觉底边校准
|
||
- 对战预览里主角和对手要沿画面中线成对出现,但纵向不能只共用一个 `bottom` 常量。
|
||
- 怪物精灵帧的空白、体型和脚底位置差异很大,运行画面应按帧高分档下沉,让怪物视觉底边落在主角同一条地面线上。
|
||
- 后续新增怪物资源时,先检查红圈标注的实际落点,再调整锚点分档或单怪物偏移,避免出现“悬在地面上方”的状态。
|
||
- 自定义世界里敌对角色已经先作为场景 NPC 存在,即使它同时携带 `characterId` 和 `monsterPresetId`,画布也不能直接沿用模板角色的 `groundOffsetY`;只要 encounter 自身有 `imageSrc` 或 `visual`,就按场景 NPC 自定义形象锚点处理。
|
||
- 幕预览运行时还会构造“无 `characterId`、但有 `visual` 的场景 NPC”,这类和平相遇分支同样必须套用场景 NPC 自定义形象锚点,否则会停在画面中上部。
|
||
|
||
### 10.3 移动端固定整页画布缩放
|
||
- 主站移动端以固定游戏画布体验为准,入口 `viewport` 需要锁定 `minimum-scale=1.0`、`maximum-scale=1.0` 和 `user-scalable=no`,同时保留 `viewport-fit=cover` 适配安全区。
|
||
- 浏览器仍可能通过 iOS `gesture*` 或多指 `touchmove` 触发整页缩放,因此主站启动入口应统一调用 `lockMobileViewportZoom()` 拦截页面级捏合与快速双击缩放。
|
||
- 不要在每个画布组件里重复注册缩放拦截;单指滚动、点击、拖拽应继续留给具体页面和玩法处理。
|