# 智绘微刻小程序 - UI 覆层组件文档
本文档说明两个全局 UI 覆层能力:**顶部滚动遮罩(ScrollTopMask)** 和 **自定义 Tab Bar(CustomTabBar)**。
---
## 一、顶部滚动遮罩 ScrollTopMask
### 作用
信息流页面上下滚动时,在页面顶部形成分层模糊 + 渐变透明遮罩:
- 上滑到大标题接近状态栏区域时遮罩淡入,状态栏时间/电量更清晰;
- 遮罩内水平居中显示当前页面标题,标题位于遮罩下 1/4 区域(`bottom: 38%`);
- 下拉回顶时按相同进度淡出;
- 大标题本身仍随页面自然滚动,不做吸顶/缩放/变色。
### 组件位置
```text
src/components/ScrollTopMask/
├── index.tsx # 组件逻辑
└── index.scss # 模糊层 / 渐变层 / 标题样式
```
### 使用方式
在任意页面的根 View(`theme-*` 容器)内、`` 之后放置:
```tsx
import ScrollTopMask from '../../components/ScrollTopMask'
{/* 页面内容 */}
```
> 二级页面(`src/pages/shop/detail`、`src/pages/diy/stickerEdit` 等)相对路径为 `../../../components/ScrollTopMask`。
二级页面开启返回按钮(`showBack`),遮罩随滚动淡入时,左上角会显示 `←` 返回按钮,点击回调 `Taro.navigateBack()`:
```tsx
```
当前开启 `showBack` 的页面:商品详情、产品详情、设计工作台、贴纸编辑、结算、订单详情、收货地址、设置、AI 词云。
### Props
| Prop | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| `title` | `string` | 是 | - | 遮罩内居中显示的标题文本 |
| `targetSelector` | `string` | 否 | `.page-header` | 顶部测量节点,用于计算遮罩出现的滚动阈值 |
| `showBack` | `boolean` | 否 | `false` | 是否在遮罩左上方显示返回按钮(二级页面用) |
`targetSelector` 按页面页头选择:
| 页面 | title | targetSelector |
|---|---|---|
| 首页 `index` | 智绘微刻 | `.home-header` |
| 商品 `shop/index` | 智绘精选 | `.shop-header` |
| 设计清单 `designList` | 我的设计清单 | `.page-header.design-header` |
| 订单 `orders` | 我的订单 | `.orders-page .page-header` |
| 我的 `profile` | 我的 | `.profile-header` |
| 商品详情 `shop/detail` | 商品详情 | `.shop-back-btn` |
| 产品详情 `product` | 商品详情 | `.page-header` |
| 订单详情 `orderDetail` | 订单详情 | `.page-header` |
| 设计工作台 `diy` | 设计工作台 | `.page-header.surface-card` |
| 贴纸编辑 `diy/stickerEdit` | 编辑贴纸 | `.edit-header` |
| 结算 `checkout` | 设计效果确认 | `.page-header` |
| 收货地址 `address` | 收货地址 | `.page-header` |
| 设置 `settings` | 设置 | `.page-header.settings-header` |
| 客服 `service` | 联系客服 | `.page-header.service-header` |
| 定制协议 `agreement` | 定制协议 | `.agreement-title` |
| AI 词云 `wordcloud` | AI词云生成 | `.page-header.cloud-header` |
| 用户数据库 `userDatabase` | 本地用户数据库 | `.page-header.udb-header` |
### 实现原理
1. `useSafeArea()` 提供状态栏 / 胶囊按钮安全区;
2. `Taro.usePageScroll` 监听页面滚动(Taro 3 子组件可通过页面 Context 注册);
3. `createSelectorQuery().select(targetSelector)` 测量页头位置;
4. `getTopMaskStartY` 把「视口相对 bottom + 当前 scrollTop」换算成文档相对阈值,避免提前滚动导致阈值塌缩;
5. `getTopMaskProgress` 输出 0~1 遮罩进度,节流到定时器内更新;
6. 标题淡入使用二次映射:遮罩进度 0.5 后才开始出现。
### 视觉参数(当前值)
| 参数 | 值 | 位置 |
|---|---|---|
| 中模糊层 | `blur(12rpx)`,纵向淡出到 76% | `index.scss` |
| 弱模糊层 | `blur(6rpx)`,纵向淡出到 100% | `index.scss` |
| 渐变层高度 | mask 高度的 80% | `index.scss` |
| 渐变顶部不透明度 | `0.94` | `index.scss` |
| 渐变 50% 处 | `0.9` | `index.scss` |
| 渐变 78% 处 | `0.58`,之后到 0 | `index.scss` |
| 标题位置 | `bottom: 38%`,水平居中 | `index.scss` |
| 遮罩高度 | `max(menuButtonTop+menuButtonHeight+18, statusBarHeight+52) + 24(px)` | `index.tsx` |
### 注意事项
- 遮罩 `pointer-events: none`,不影响点击;二级页左侧返回按钮仍可操作;
- 多层 `backdrop-filter` + `mask-image` 真机兼容性需要实测,不支持的设备会退回纯渐变;
- 修改视觉参数只需改 `src/components/ScrollTopMask/index.scss`,无需逐页调整。
---
## 二、自定义 Tab Bar CustomTabBar
### 作用
微信自定义 tabBar,提供毛玻璃悬浮胶囊导航 + 浅色/深色主题自适应 + 路由切换联动。
### 组件位置
```text
src/custom-tab-bar/
├── index.json
├── index.tsx # tab 配置与切换逻辑
└── index.scss # 毛玻璃 / 渐变 / 主题样式
```
### 启用方式
`src/app.config.ts`:
```ts
tabBar: {
custom: true,
list: [
{ pagePath: 'pages/index/index', text: '首页' },
{ pagePath: 'pages/shop/index', text: '商品' },
{ pagePath: 'pages/designList/index', text: '设计清单' },
{ pagePath: 'pages/orders/index', text: '订单' },
{ pagePath: 'pages/profile/index', text: '我的' }
]
}
```
### Tab 配置
`src/custom-tab-bar/index.tsx` 顶部 `TABS` 数组驱动渲染:
```ts
const TABS = [
{ pagePath: '/pages/index/index', label: '首页', icon: assetUrl('/icon/首页.svg'), iconActive: assetUrl('/icon/首页-fill.svg') },
// ...
]
```
新增/调整 Tab 时需要同时同步:
1. `TABS` 数组(label、pagePath、icon、iconActive);
2. `src/app.config.ts` 的 `pages` 与 `tabBar.list`;
3. 对应图标资源。
### 核心行为
- 选中态由内部 `activeTab` state 维护(自定义 tabBar 不在 React Tree 内,不依赖路由自动感知);
- `switchTab` 调用 `Taro.switchTab` 并触发 `tabBarChange` 事件,页面内部也监听该事件同步选中态;
- 主题:监听 `THEME_CHANGE_EVENT` + 系统 `onThemeChange`,`auto` 跟随系统,并调用 `applyPageBackground` 兜底刷新页面背景;
- 样式:底部渐变托底 + 悬浮胶囊,`backdrop-filter: blur(32px) saturate(1.2)`,浅/深主题各自配色。
### 注意事项
- `z-index`:渐变托底 `999`,胶囊 `1000`,浮于页面内容之上;
- 自定义 tabBar 与顶部 ScrollTopMask 互不冲突(遮罩 z-index 40,位于胶囊之下的页面层级);
- 修改样式只需改 `src/custom-tab-bar/index.scss`。
---
## 相关文件索引
| 文件 | 作用 |
|---|---|
| `src/components/ScrollTopMask/index.tsx` | 顶部遮罩组件逻辑 |
| `src/components/ScrollTopMask/index.scss` | 顶部遮罩视觉参数 |
| `src/custom-tab-bar/index.tsx` | 自定义 Tab Bar 逻辑与 Tab 配置 |
| `src/custom-tab-bar/index.scss` | 自定义 Tab Bar 样式 |
| `src/utils/homeTopMask.js` | 遮罩进度 / 阈值纯函数 |
| `tools/homeTopMask.test.mjs` | 遮罩纯函数单测 |
| `src/app.config.ts` | 页面路由与 tabBar 注册 |