进入下面小程序可以体验效果:
基于官方原版demo加入了回弹动画
WXML:
<scroll-viewclass="scroll-area"type="custom"scroll-yshow-scrollbar="{{false}}"worklet:onscrollend="handleScrollEnd"worklet:onscrollupdate="handleScrollUpdate"
><view class="fake-nav-bar" /><sticky-section push-pinned-header="{{false}}"><sticky-header><view class="search-container"><view class="search"><view class="search-icon-wrp"><image class="search-icon" src="/assets/image/search.png" /></view><view class="search-text">搜索</view><view class="search-btn">搜索</view></view></view></sticky-header><view>1211111111111111111111111111111111</view><view>1211111111111111111111111111111111</view></sticky-section>
</scroll-view>
js:
const app = getApp() //这段代码需要放在page页面JS的最顶部
const systemInfo = wx.getSystemInfoSync()const { shared, Easing,spring ,timing,sequence,delay} = wx.workletconst lerp = function (begin, end, t) {'worklet'return begin + (end - begin) * t
}const clamp = function (cur, lowerBound, upperBound) {'worklet'if (cur > upperBound) return upperBoundif (cur < lowerBound) return lowerBoundreturn cur
}Page({/*** 页面的初始数据*/data: {},/*** 生命周期函数--监听页面加载*/onLoad(options) {this.saftPadding = shared(0)this.searchBarheight = shared(0)this.searchBarWidth = shared(100)this.searchBarLeft = shared(0)this.navBarOpactiy = shared(1)this.isTop = shared(false) //是否触顶了this.isBottom = shared(false) //是否触底了this.isExc = shared(false) //是否执行动画了this.isScrolling = shared(false) //是否正在滑动},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {this.applyAnimatedStyle('.nav-bar', () => {'worklet'return {opacity: this.navBarOpactiy.value}})this.applyAnimatedStyle('.search', () => {'worklet'return {width: `${this.searchBarWidth.value}%`,left: `${this.searchBarLeft.value}%`,height: `${this.searchBarheight.value}px`}})this.applyAnimatedStyle('.search-container', () => {'worklet'return {backgroundColor: (this.navBarOpactiy.value > 0) ? 'transparent' : '#fff',paddingTop: `${this.saftPadding.value}px`}})wx.nextTick(()=>{//胶囊顶部位置(安全位置)this.saftPadding.value = app.globalData.menu.top// //胶囊高度this.searchBarheight.value = app.globalData.menu.height})},handleScrollUpdate(evt) {'worklet'const maxDistance = 60const scrollTop = clamp(evt.detail.scrollTop, 0, maxDistance)const progress = scrollTop / maxDistanceconst EasingFn = Easing.cubicBezier(0.4, 0.0, 0.2, 1.0)this.searchBarLeft.value = lerp(0, 25, EasingFn(progress))this.navBarOpactiy.value = lerp(1, 0, progress)const t1= lerp(100, 45, EasingFn(progress))if(t1>45&&t1<100){this.isScrolling.value=true}if((t1>45&&t1<100)&&(!this.isExc.value||this.isScrolling.value)){this.searchBarWidth.value = t1-1.5}if(t1===45&&evt.detail.scrollTop>60&&!this.isTop.value){//靠顶了this.isTop.value=truethis.isBottom.value=falsethis.searchBarWidth.value = t1-2this.searchBarWidth.value = spring(t1)this.isExc.value=truethis.isScrolling.value=false}else if(t1===100&&evt.detail.scrollTop<2&&!this.isBottom.value){//靠底了this.isBottom.value=truethis.isTop.value=falsethis.searchBarWidth.value = t1-2this.searchBarWidth.value = spring(t1)this.isExc.value=truethis.isScrolling.value=false}},handleScrollEnd(evt){'worklet'this.isScrolling.value=falsethis.isExc.value=false},
/*** 生命周期函数--监听页面显示*/onShow(){},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
WXSS:
.fake-nav-bar {height: 60px;}.search-container {padding: 0 16px 10px 16px;}.search {display: flex;flex-direction: row;box-sizing: border-box;width: 100%;height: 40px;border-radius: 20px;border: 2px solid #07c160;position: relative;align-items: center;background-color: #fff;}.search-text {color: #8f8888;font-size: 14px;}.search-icon-wrp {display: flex;width: 30px;height: 100%;flex-direction: row;align-items: center;justify-content: center;}.search-icon {width: 16px;height: 16px;}.search-btn {position: absolute;right: 0;width: 60px;height: 100%;border-radius: 20px;background-color: #07c160;display: flex;align-items: center;justify-content: center;color: #FFF;font-size: 16px;/* font-weight: bold; */}.nav-bar {background-color: #fff;position: absolute;}.nav-left {display: flex;flex-direction: row;align-items: center;}.nav-logo {width: 40px;height: 40px;border-radius: 50%;}.nav-title {margin-left: 2px;font-size: 20px;color: #3f3e3e;/* font-weight: bold; */}.scroll-area {height: 100vh;}