# UI 改动记录(供后续 Agent 阅读) 本文档汇总 **像素 RPG UI 皮肤化** 相关实现与决策,便于新会话快速接手。更细的命名与规范见同目录上一级的 **`UI_CODING_STANDARD.md`**。 --- ## 1. 相关文件一览 | 路径 | 作用 | |------|------| | `UI_CODING_STANDARD.md` | 资源目录约定、9-slice 规则、图标语义、`Icons`/`UI` 命名解读、已知问题(含世界按钮切片) | | `src/uiAssets.ts` | **唯一推荐** 的 UI 资源映射:`UI_CHROME`(9-slice 配置)、`TAB_ICONS`、`WORLD_SELECT_ICONS`、`getNineSliceStyle()` | | `src/components/PixelIcon.tsx` | 小图标 ``,`image-rendering: pixelated` | | `src/index.css` | `.pixel-nine-slice`、`.pixel-root-shell` / `.pixel-app-shell`、tab/按钮布局类、`--ui-scale` | | `src/App.tsx` | 世界选择、角色卡、底部 tab、剧情/背包面板、地图弹窗、`MudMapRoom` | | `src/components/GameCanvas.tsx` | 场景名按钮(9-slice `Title_frame_m`) | | `vite.config.ts` | `root` / `envDir` 指向 `__dirname`,保证 `.env.local` 从项目根加载 | | `public/UI/`、`public/Icons/` | 静态资源(路径以 `/UI/...`、`/Icons/...` 引用) | --- ## 2. 架构要点 ### 2.1 9-slice(禁止整图 `background-size: 100% 100%` 拉框体) - 使用 CSS **`border-image`** + **`fill`**,通过自定义属性注入切片参数。 - 类名:**`pixel-nine-slice`**(定义在 `src/index.css`)。 - 行内样式由 **`getNineSliceStyle(texture, overrides?)`** 生成(`src/uiAssets.ts`),设置 `--frame-src`、`--slice-*`、`--frame-pad-*`、`--frame-repeat`、可选 `--frame-base`(一般仅在图源中心确实透明时使用)。 ### 2.2 响应与缩放 - `:root` 上 **`--ui-scale`**:`clamp`(桌面)+ 小屏媒体查询内固定约 `0.8`。 - 边框宽度 = 切片像素 × `--ui-scale`,与 padding 同逻辑,避免移动端边框比例失控。 ### 2.3 交互 - **`pixel-pressable`**:hover 用 `translateY` + `brightness`,**避免**对像素框体做 `scale()` 以免糊边。 ### 2.4 全局背景 - **根布局**(`App.tsx` 最外层):`pixel-root-shell` + `Background_fill.png` 平铺 + 深色半透明渐变(替代纯 `#050505` 死底)。 - **下半屏内容区** `pixel-app-shell`:同一纹理 + **更轻**的遮罩,让纹理更明显。 - 开局标题区已去掉单独 `bg-zinc-950`,与根背景一致。 --- ## 3. `UI_CHROME` 当前用途(速查) 以下为 `src/uiAssets.ts` 中主要键与界面位置的对应关系(切片数值以文件内为准): | Key | 资源(示例) | 用途 | |-----|----------------|------| | `appBackground` | `Background_fill.png` | 根壳 + 下半屏平铺底 | | `worldButtonWuxia` / `worldButtonXianxia` | `1_orange_button` / `1_violet_button` | 开局武侠/仙侠(**条高 28px**,切片见下文) | | `characterCardFrame` | `pick_hero_frame` | 选角卡片 | | `tabActive` / `tabInactive` | `Shop_tab_picked` / `Shop_tab` | 底部「角色 / 冒险 / 背包」 | | `panel` | `Frame_bg_big_2` | 装备区等通用面板 | | `storyPanel` | `Dialogue_frame` | 剧情正文区 | | `inventoryPanel` | `Inventory_bg` | 背包条目 | | `statsPanel` | `Stats_bar` | 角色数值面板 | | `choiceButton` | `Options_bar` | 剧情选项按钮 | | `modalPanel` | `Popup_window` | 地图弹窗外壳 | | `infoPanel` | `Dialogue_frame` | 地图弹窗内「当前地点 / 可前往」信息块 | | `sceneTitle` | `Title_frame_m` | 战斗画布顶部场景名按钮 | | `mapRoomCell` | `Map_frame` | 地图节点卡片(`MudMapRoom`) | | `mapDiagramPanel` | `Frame_bg_big_2` | 地图关系图整体衬底 | 图标路径:`TAB_ICONS`、`WORLD_SELECT_ICONS`、`CHROME_ICONS`;装备槽与背包分类见 `getEquipmentSlotIcon` / `getInventoryCategoryIcon`。 --- ## 4. 已知坑(必读) ### 4.1 世界选择按钮「中间发空」 - 图源 **`1_orange_button.png` / `1_violet_button.png` 为 125×28**。 - 若 **`slice.top + slice.bottom >= 28`**,中间横带高度为 **0**,`border-image` 的 `fill` 异常,看起来像透明/没画上。 - **正确做法**:减小上下切片(当前为 **9+9**),并配合 `repeat: 'stretch'` 竖向拉伸条形成品。 - **不推荐**:用大色块 `baseColor` 糊底(与素材内渐变/内框不一致)。详见 `UI_CODING_STANDARD.md`「已知问题」。 ### 4.2 新增 9-slice 前 先读 PNG **宽高**,保证 **`top+bottom < height`** 且 **`left+right < width`**。 --- ## 5. 环境与运行(与 UI 无关但易踩坑) - LLM:`VITE_LLM_*` 写在项目根 **`.env.local`**;因 `vite.config.ts` 固定 `envDir: __dirname`,从任意 cwd 启动也应能读到。 - 开发:`npm run dev`(默认端口见 `package.json`)。 --- ## 6. 尚未统一成 UI 图、仍用 Tailwind 小块面的区域(可选后续) 若产品要求「全盘无纯色板」,可继续替换,当前仍可能为 `bg-black/20`、`rounded-lg border` 等: - 角色页装备行、属性格子 - 地图弹窗顶栏分隔、关闭按钮外圈 - `GameCanvas` 内血条、名字条等 HUD --- ## 7. 修改清单摘要(按主题) 1. **资源规范**:`UI_CODING_STANDARD.md` + 集中映射 `uiAssets.ts`。 2. **9-slice 系统**:`index.css` + `getNineSliceStyle`。 3. **开局 / 主界面**:世界按钮、选角卡、tab、面板、选项、背包、根与内容区背景纹理。 4. **地图弹窗**:外壳、信息板、节点 `Map_frame`、关系图 `Frame_bg_big_2`。 5. **画布**:场景名 `Title_frame_m`。 6. **世界按钮**:按真实像素尺寸修正切片,去掉错误 `baseColor` 方案。 7. **Vite**:`root`/`envDir` 保证环境变量加载稳定。 --- *文档目的:交接给下一个 Agent 时,优先读本文件 + `UI_CODING_STANDARD.md`,再改 `uiAssets.ts` / `App.tsx` / `index.css`。*