185 lines
7.1 KiB
Markdown
185 lines
7.1 KiB
Markdown
# 智绘微刻小程序 - UI 覆层组件文档
|
||
|
||
本文档说明两个全局 UI 覆层能力:**顶部滚动遮罩(ScrollTopMask)** 和 **自定义 Tab Bar(CustomTabBar)**。
|
||
|
||
---
|
||
|
||
## 一、顶部滚动遮罩 ScrollTopMask
|
||
|
||
### 作用
|
||
|
||
信息流页面上下滚动时,在页面顶部形成分层模糊 + 渐变透明遮罩:
|
||
|
||
- 上滑到大标题接近状态栏区域时遮罩淡入,状态栏时间/电量更清晰;
|
||
- 遮罩内水平居中显示当前页面标题,标题位于遮罩下 1/4 区域(`bottom: 38%`);
|
||
- 下拉回顶时按相同进度淡出;
|
||
- 大标题本身仍随页面自然滚动,不做吸顶/缩放/变色。
|
||
|
||
### 组件位置
|
||
|
||
```text
|
||
src/components/ScrollTopMask/
|
||
├── index.tsx # 组件逻辑
|
||
└── index.scss # 模糊层 / 渐变层 / 标题样式
|
||
```
|
||
|
||
### 使用方式
|
||
|
||
在任意页面的根 View(`theme-*` 容器)内、`<ThemedPageMeta />` 之后放置:
|
||
|
||
```tsx
|
||
import ScrollTopMask from '../../components/ScrollTopMask'
|
||
|
||
<View className={`theme-${resolvedTheme}`}>
|
||
<ThemedPageMeta />
|
||
<ScrollTopMask title="页面标题" targetSelector=".page-header" />
|
||
{/* 页面内容 */}
|
||
</View>
|
||
```
|
||
|
||
> 二级页面(`src/pages/shop/detail`、`src/pages/diy/stickerEdit` 等)相对路径为 `../../../components/ScrollTopMask`。
|
||
|
||
二级页面开启返回按钮(`showBack`),遮罩随滚动淡入时,左上角会显示 `←` 返回按钮,点击回调 `Taro.navigateBack()`:
|
||
|
||
```tsx
|
||
<ScrollTopMask title="商品详情" targetSelector=".page-header" showBack />
|
||
```
|
||
|
||
当前开启 `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 注册 |
|