需要实现的效果:
markdown
1. 顶部标题栏置顶实现
2. 监听滚动使Tab切换区域动态置顶
3. 多模块置顶衔接与背景图处理
① 滑动前效果:

② 滑动中效果:

③ 双置顶效果:

技术实现
1、顶部导航栏置顶
分析:
1、顶部导航栏置顶,只需借助vant组件 fixed设置为true即可。
2、页面滑动时,导航栏背景图与页面背景图一致,因此需要给导航栏添加页面背景图。
html
<van-nav-bar
title="{{pageTitle}}"
border="{{false}}"
fixed="{{true}}"
custom-class="nav-style"
custom-style="background-image: url({{bgUrl}});"
>
</van-nav-bar>
2、监听滚动使Tab切换区域动态置顶
分析:
-
滚动监听实现方式
- 采用页面级监听:使用onPageScroll方法
- 或使用组件级监听:通过scroll-view的bind:scroll事件
- 两种方式均可实时获取当前scrollTop值
-
置顶逻辑实现要点
- 当tab区域滑动至导航栏位置时触发置顶
- 当tab区域离开导航栏位置时取消置顶
- 关键计算步骤:
- 通过boundingClientRect()获取tab区域位置(tabScrollTop)
- 置顶临界值 = scrollTop -
tabTop + 导航栏高度 - 使用wx.getMenuButtonBoundingClientRect()将导航栏高度menuHeight变为可控变量。
获取导航栏高度:
javascript
wx.getSystemInfo({
success: res => {
// 导航栏.top 导航栏.bottom 导航栏.height
let menuButtonRect = wx.getMenuButtonBoundingClientRect()
this.setData({
menuHeight: menuButtonRect.bottom
})
console.log('导航栏高度', this.data.menuHeight)
}
})
导航栏样式:
在上面背景图的基础上增加固定高度样式
导航栏可用内容高度:36px
不可用区域padding-top值: menuHeight - 36px
底部留白:padding-bottom: 12px;
总高度:menuHeight + 12px
tab执行位置:menuHeight + 12px
html
<van-nav-bar
title="{{pageTitle}}"
border="{{false}}"
fixed="{{true}}"
custom-class="nav-style"
custom-style="background-image: url({{bgUrl}}); height: 36px; line-height: 48px; padding-bottom: 12px;padding-top: {{menuHeight - 36}}px"
>
</van-nav-bar>
获取tab区域tabTop值:
javascript
setTimeout(() => {
let query = this.createSelectorQuery().in(this)
query.selectViewport().scrollOffset();
query.select('#sticky-container').boundingClientRect();
query.exec(res => {
this.setData({
stickyTop: res[1].top,
})
})
})
监听滚动设置置顶:
javascript
onScroll(el) {
let scrollTop = el.detail.scrollTop
let tabTop = this.data.stickyTop
let topNavHeight = this.data.menuHeight + 12
if(scrollTop >= tabTop - topNavHeight) {
this.showFixed(true) // 显示执行样式
}else {
this.showFixed(false) // 取消执行样式
}
}
背景衔接处理
html
<view
wx:if="{{isFixed && list.length > 0}}"
class="sticky-container sticky-fixed"
style="top: {{menuHeight + 12}}px;background-image: url({{bgUrl}});background-position: 0 -{{menuHeight + 12}}px;"
>
</view>
<view wx:if="{{!isFixed && list.length > 0}}" class="sticky-fixed" >
</view>