首頁 > 軟體

微信小程式實現頂部固定 底部分頁捲動效果

2022-10-12 14:00:42

常見商品頁效果:頂部banner+分類,下面商品列表。

方案說明:

方案1:整個頁面捲動,捲動至某個位置fixed圖中“頂部box2”,分頁頁面觸底載入

方案2:頁面高度為螢幕高度,商品部分使用scroll-view,scroll-view初始高度為螢幕高度-頂部高度,只捲動scroll-view。

思路說明:

  1 將整個頁面分為上下兩部分,整個頁面高度100vh(原因1:scroll-view高度需要固定高度;原因2:出現兩個卷軸)

  2 頁面上半部分包括banner(box1)以及固定的搜尋及tab(box2)

  3 根據頂部box的高度,算出下面scroll-view的高度(windowHieght - 200)

  4 scroll-view滑動到 頂部box1+margin10的高度,將box1隱藏,box2動畫移至頂部;下面scroll高度+捲動高度(或box1高度) + margin10高度(確保scroll的商品吸頂之後任然沾滿螢幕)

方案3:使用外掛

選擇的是方案2,為什麼不選擇方案1,我們來剖析一下。

方案1適合頁面互動比較簡單,根據頁面捲動高度隱藏展示即可。

  場景1:tab吸頂之後,切換tab請求資料,頁面就會渲染為最初樣式,不會吸頂。(請求會重新setData資料,有些資料有多有少)

複製以下程式碼可以直接演示demo效果

demo.wxml

<!--pages/demo/demo.wxml-->
<view class="wrap">
  <view class="top-box" style="{{boxStyle}}">
    <view class="top-box1" style="{{box1Style}}">頂部box1</view>
    <!-- <view class="top-box2"></view> -->
    <scroll-view class="top-box2" scroll-into-view="{{scrollId}}" scroll-x="true"scroll-with-animation="true" >
      <block wx:for="{{cates}}" wx:key="index">
        <view class="{{item.id === currentId?'cate-item-act cate-item':'cate-item'}}" data-id="{{item.id}}" id="good{{item.id}}" bindtap="cateChange">{{item.name}}</view>
      </block>
    </scroll-view>
  </view>
  <scroll-view scroll-y="true" class="scroll-con" style="{{scrollViewStyle}}" bindscroll="goodsViewScroll" bindscrolltoupper="goodsViewScrollTop">
    <view class="scroll-con-item" wx:for="{{cates}}" wx:key="index">{{item.name}}</view>
  </scroll-view>
</view>

demo.js

Page({
  data: {
    cates:[
      {id:null,name:'全部'},
      {id:1,name:'分類1'},
      {id:2,name:'分類2'},
      {id:3,name:'分類3'},
      {id:4,name:'分類4'},
      {id:5,name:'分類5'},
      {id:6,name:'分類6'},
      {id:7,name:'分類7'},
      {id:8,name:'分類8'}
    ],
    currentId:null,
    serviceList:[
      {id:1,name:'1'},
      {id:2,name:'2'},
      {id:3,name:'3'},
      {id:4,name:'4'},
      {id:5,name:'5'},
      {id:6,name:'6'},
      {id:7,name:'7'},
      {id:8,name:'8'}
    ],
    scrollId:null,//滑動id,切換tab效果
    animationStyle:'',
    isNeedFixed:false
  },
  /**
   * 生命週期函數--監聽頁面載入
   */
  onLoad(options) {
    let that = this;
    wx.getSystemInfo({
      success: function (res, rect) {
        that.setData({
          // 商品scroll高度 = 可使用視窗 - (頂部box的高度+margin20 -20(底部留白))
          scrollViewHeight: parseInt(res.windowHeight - 220 -20),
          scrollViewStyle:`height:${parseInt(res.windowHeight - 220-20)}px`
        })
      }
    })
  },
  cateChange(e){
    let currentId = e.currentTarget.dataset.id;
    let scrollId = e.currentTarget.id;
    this.setData({
      currentId,
      scrollId
    })
  },
  // 加this.data.isNeedFixed條件防止頻繁的setdata
  // 1 隱藏box1,box2會自動吸頂 box2置頂
  // 2 設定scroll-view高度+120, 設定頂部box高度為box2高度
  goodsViewScroll(e){
    console.log(e.detail.scrollTop, this.data.isNeedFixed)
    if(e.detail.scrollTop >= 120 ){
      console.log('可以動畫調整位置了')
      this.setData({
        isNeedFixed:true,
        box1Style:`height:0px;`,
        boxStyle:`height:80px;`,
        scrollViewStyle: `height:${this.data.scrollViewHeight + 120}px`,  
      }
    }
    // if(e.detail.scrollTop < 120 ) {
    //   console.log('需要保持原樣')
    //   this.setData({
    //     isNeedFixed:false,
    //     box1Style:`height:110px;`,
    //     boxStyle:`height:200px;`,
    //     scrollViewStyle: `height:${this.data.scrollViewHeight}px`,
    //   },()=>{
    //     wx.pageScrollTo({
    //       scrollTop: 0,
    //     })
    //   })
    // }
  },

  goodsViewScrollTop(e){
       this.setData({
        isNeedFixed:false,
        box1Style:`height:110px;`,
        boxStyle:`height:200px;`,
        scrollViewStyle: `height:${this.data.scrollViewHeight}px`,
      })
  }
})

demo.wxss

.wrap {
  height: 100vh;
}
.top-box {
  height: 200px;
  height: 200px;
  background-color: #fff;
  border: 1px solid #d1d1d1;
  transition:height 0.2s;
    -webkit-transition:height 0.2s; /* Safari */
}
.top-box1 {
  height: 110px;
  width: 100%;
  margin-bottom: 10px;
  background-color: #3293FF;
  overflow: hidden;
  transition:height 0.2s;
  -webkit-transition:height 0.2s; /* Safari */
}
.top-box2 {
  height: 80px;
  width: 100%;
  background-color: #ffbe32;
  white-space: nowrap;
  padding: 50rpx 0;
  box-sizing: border-box;
}
.top-box2 .cate-item {
  display: inline-block;
  padding: 10rpx 20rpx;
  font-size: 26rpx;
  margin-right: 20rpx;
  color: #767A84;
}
.top-box2 .cate-item:last-child{
  margin-right: 0rpx;
}
.top-box2 .cate-item-act {
  background: #3293FF;
  color: #fff;
  border-radius: 48rpx;
}
.scroll-con {
  padding: 0 10px;
  margin-top: 20px;
  box-sizing: border-box;
  background-color: #fff;
}
.scroll-con-item {
  height: 100px;
  width: 100%;
  background-color: salmon;
  margin-bottom: 10px;
}
.ani-btn {
  display: inline-block;
  padding: 20rpx;
  margin: 10rpx;
  border: 1px solid #d1d1d1;
}
@keyframes move{ from{transform: translateY( 30px)} to {transform: translateY( 0px)}}

說明1:scroll-into-view 設定哪個方向可捲動,則在哪個方向捲動到該元素

  scroll-view設定x軸捲動到scrollId位置 scroll-x="true"scroll-into-view="{{scrollId}}"    

  item子元素設定id="good{{item.id}}" 由於id不能已數位開頭,所以前面拼了"good"

說明2:為什麼要在bindscrolltoupper觸頂事件中處理初始化樣式,而不是在bindscroll的時候處理?

  使用bindscroll處理,滑動會有來回閃動的情況

這些只是大致思路,還有很多細節需要處理和考.......

到此這篇關於微信小程式實現頂部固定 底部分頁捲動效果的文章就介紹到這了,更多相關小程式頂部固定內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com