# 08 — 面板改为右边缘滑出,并让它能在静态托管上工作 Status: resolved Type: task ## 需求(用户原话) > 模拟的壁纸测试面板是在鼠标移至页面右侧边缘时弹出的,且并不能仅有调试服提供,未来上传 GitHub 是 pages 预览也需要能够弹出壁纸设置面板 两件事: 1. 面板的打开方式是**鼠标移到页面右侧边缘**——不是常驻按钮。 2. 面板**不能只有调试服能给**。未来上 GitHub Pages 的预览也要能弹出设置面板。 ## ① 交互:右边缘滑出 原来的实现是右上角一个常驻的「WE 模拟器」按钮。改成 16px 右边缘热区 + 全高抽屉,与 player 配置页同一套约定: | 行为 | 结果 | | --- | --- | | 指针进入右边缘 16px | 面板滑出 | | 指针离开面板/边缘 | 自动收回 | | 点 × 收起 | 收起,且**必须先离开边缘**才会再次自动滑出 | | 点热区 | 开合(触屏没有 hover,点击是兜底) | `#wesim-edge` 里的把手只是"这里能滑出东西"的可见提示,`pointer-events: none`,不参与命中。 ### 踩的坑:不能用 mouseenter / mouseleave 判定 第一版用 `edge.mouseenter` 打开、`root.mouseleave` 收回。测试立刻发现"指针离开 → 自动收回"永远是 `data-open=1`。 原因:面板是用 `transform` 从右侧滑进来的,**出现时指针已经在它下面**,浏览器不会为它补发 `mouseenter`——于是 `root` 从来没被标记为 hover,它后面的 `mouseleave` 自然也不会来。 改成在 `mousemove` 里按坐标判定,结果只取决于指针位置,与浏览器是否补发事件无关: ```js const nearEdge = event.clientX >= window.innerWidth - EDGE_WIDTH; const overPanel = opened && event.clientX >= window.innerWidth - PANEL_WIDTH; ``` `PANEL_WIDTH` / `EDGE_WIDTH` 与 CSS 共用同一组常量(CSS 里用模板插值),避免"改了一处忘了另一处"。 `armed` 是"× 收起后需先离开边缘"那条规则的状态位。没有它,点 × 之后指针仍在热区里,下一次 `mousemove` 就把面板弹回来,表现为"× 根本关不掉"。 ## ② 静态托管:把注入写进 index.html | 场景 | 谁注入 | 模拟器本体从哪来 | 产物 | | --- | --- | --- | --- | | `pnpm dev` | 调试服按路由注入 | 调试服自己的 `/simulator/wallpaper-engine.js` | 分发目录保持干净 | | 静态托管(Pages) | 构建期写进 `index.html` | 分发自带的 `./scripts/wallpaper-engine.js` | `pnpm build --with-sim` | | 上传 Wallpaper Engine | 没有人注入 | 不存在 | `pnpm build`(默认) | 要点: - 静态地址**必须相对**(`./scripts/...`)。Pages 把站点放在 `//` 子路径下,根绝对路径会 404。 - 驱动带幂等闸 `window.__weSimDriver`:`--with-sim` 构建的分发自带驱动,调试服又会注入一次,没有闸就会 mount 两遍、出现两个面板。 - 默认产物里**既没有模拟器文件,也没有任何注入痕迹**——它必须与用户从创意工坊下载到的东西完全一致(ADR 0006 第 1 条)。 ## 验证 `tools/checks/verify-static-preview.mts`:**刻意把分发挂在 `/repo/` 前缀后面服务**,而不是挂在根上——挂根上测不出相对路径的错。断言分三组: - 静态托管下 `window.__weSim` 存在、`#wesim` 与 `#wesim-edge` 已挂载、没有常驻按钮、横幅在、壁纸本身也渲染 - 右边缘滑出六态:初始收起 → 滑出 → 离开收回 → 再滑出 → × 收起不被弹回 → 离开边缘后重新可触发 - 静态服务器 **0 个 404**、0 异常、0 控制台报错 四档分发全部通过。另有 `tools/checks/smoke-sim.mts` 的"面板恰好一个"断言守住双重注入。 ## 顺带发现 - 合集那两档的自包含包是 128.7 MB,**超过 GitHub 单文件 100 MB 上限**。所以 Pages 只能走"分发目录 + 构建期注入"这条路,不能直接发布 `sim/index.html`。 - `src/vendor/spine-player.js.bak` 是内联守卫测试留下的残留,已删。