需求描述: 一个小程序页面滚动,切换tab的需求。tab 并不是页面初始时,就固定在页面头部的,是页面滚动到某个距离时,做的吸顶效果。具体如下图:
由于,一开始,我是根据scrollHeight 介于heightArr 哪个区间,然后判断acitveIndex 的值,结果发现超级复杂,会有很多中情况,我总不能写N多if去判断吧,且这样的做法,不方便以后拓展。
所以就换了个思路。新思路如下:
首先,初始的acitveIndex 还是根据 heightArr[i] > 0
然后,切换事件,做的事情就是如下:
/**
* 切换tab
*/
handleChangeSeleted(e) {
this.setData({
showFixedMenu: true
}, () => {
const id = e.target.dataset.id
const query = wx.createSelectorQuery()
query.select(`#${ id }`).boundingClientRect()
query.select('#fixed').boundingClientRect()
query.selectViewport().scrollOffset()
query.exec(rect => {
const outSide = rect[1] !== null ? rect[1].bottom : 0
wx.pageScrollTo({
scrollTop: Math.ceil(rect[0].top + this.data.scrollTop - outSide)
})
})
})
}
这里的outSide 即为固定tab 时,下边距的可视区域的距离。那么acitveIndex就根据滚动事件去设置,所以滚动事件的实现如下:
主要是作为activeIndex 界定的参照对象不再是scrollHeight,而是fixed tab的下边界,如果一个内容区域 item !== null && item.top < outSide && item.bottom >= outSide,那么当前的内容区域,即为activeIndex。
/**
* 页面滚动
*/
onPageScroll(e: any) {
// 保存当前已经滚动的距离
this.data.scrollTop = e.scrollTop
// 吸顶效果 start
let showFixedMenu
const query = wx.createSelectorQuery().select('#menu-box').boundingClientRect()
query.exec(rect => {
if (rect[0] === null) {
return
}
const statusBarHeight = wx.getSystemInfoSync().statusBarHeight
if (rect[0].top <= statusBarHeight) {
showFixedMenu = true
} else {
showFixedMenu = false
}
if (showFixedMenu === this.data.showFixedMenu) {
return
}
this.setData({
showFixedMenu
})
})
// 吸顶效果 end
// 菜单选中 start
const scrollQuery = wx.createSelectorQuery()
scrollQuery.select('#first').boundingClientRect()
scrollQuery.select('#second').boundingClientRect()
scrollQuery.select('#third').boundingClientRect()
scrollQuery.select('#fixed').boundingClientRect()
scrollQuery.selectViewport().scrollOffset()
scrollQuery.exec(rect => {
const arr = [rect[0], rect[1], rect[2]]
const selectedIndex = arr.findIndex(item => {
const outSide = rect[3] !== null ? rect[3].bottom : 0
return item !== null && item.top < outSide && item.bottom >= outSide
})
if (selectedIndex > -1) {
this.setData({
selectedIndex
})
}
})
// 菜单选中 end
}
总结,说这是难点的问题在于思路,一开始思路陷进了死胡同,只想简单的根据滚动距离scrollHeihgt 介于哪两个heightArr 区间,然后取左区间的下标作为activeIndex,但是heightArr 有很多中可能性,不便计算。一时之间,也没有想到更好的方面,就在旧思路里,纠结了好几天,怎么计算啊???
突然有一天,灵光一闪,新思路就出现了!!!!