微信小程序Skyline搜索框吸顶到navtab胶囊位置,丝滑Q弹动画

发布于:2024-03-25 ⋅ 阅读:(78) ⋅ 点赞:(0)

进入下面小程序可以体验效果

基于官方原版demo加入了回弹动画

WXML:

<scroll-view
 class="scroll-area"
 type="custom"
 scroll-y
 show-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.worklet

const lerp = function (begin, end, t) {
  'worklet'
  return begin + (end - begin) * t
}

const clamp = function (cur, lowerBound, upperBound) {
  'worklet'
  if (cur > upperBound) return upperBound
  if (cur < lowerBound) return lowerBound
  return 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 = 60
    const scrollTop = clamp(evt.detail.scrollTop, 0, maxDistance)
    const progress = scrollTop / maxDistance
    const 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=true
        this.isBottom.value=false
        this.searchBarWidth.value = t1-2
        this.searchBarWidth.value = spring(t1)
        this.isExc.value=true
        this.isScrolling.value=false
    }else if(t1===100&&evt.detail.scrollTop<2&&!this.isBottom.value){
        //靠底了
        this.isBottom.value=true
        this.isTop.value=false
        this.searchBarWidth.value = t1-2
        this.searchBarWidth.value = spring(t1)
        this.isExc.value=true
        this.isScrolling.value=false
    }
  },

  handleScrollEnd(evt){
    'worklet'
    this.isScrolling.value=false
    this.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;
  }

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到