1. 程式人生 > 程式設計 >微信小程式自定義選單導航實現樓梯效果

微信小程式自定義選單導航實現樓梯效果

設計初衷

在開發頁面時,往往需要實現,點選頁面的導航選單頁面滾動到相應位置,滾動頁面實現選單選項的高亮。在html開發中,我們可以用到a標籤錨點實現,jq的動畫相結合實現類似效果。在框架中vant UI框架也為我們實現了這一效果。

微信小程式該如何實現??

效果展示

  • 當選單導航滾動到頁面頂部時,選單吸頂
  • 當點選選單按鈕時,切換到對應區域(過渡到該區域,有動畫效果)
  • 當內容區滾動到某類區域時,對應區域的選單按鈕高亮

微信小程式自定義選單導航實現樓梯效果

設計思路

1、吸頂效果的實現

  • 獲取選單導航距離頁面頂部距離wx.createSelectorQuery()
  • 頁面滾動監聽
  • 滾動距離與選單初始位置值比較

1) 距離

const query = wx.createSelectorQuery()
query.select('.menu_nav').boundingClientRect(function(res) {
    let obj = {}
    if (res && res.top) {
        obj[item.attr] = parseInt(res.top)
    }
}).exec()

①wx.createSelectorQuery()
返回一個 SelectorQuery 物件例項。在自定義元件或包含自定義元件的頁面中,應使用 this.createSelectorQuery() 來代替。

②SelectorQuery.select(string selector)
在當前頁面下選擇第一個匹配選擇器 selector 的節點。返回一個 NodesRef 物件例項,可以用於獲取節點資訊。

selector 語法
selector類似於 的選擇器,但僅支援下列語法。

www.cppcns.com
屬性 型別 說明
id string 節點的 ID
dataset Object 節點的 dataset
left number 節點的左邊界座標
right number 節點的右邊界座標
top number 節點的上邊界座標
bottom number 節點的下邊界座標
width number 節點的寬度
height number 節點的高度

③NodesRef.boundingClientRect(function callback)
新增節點的佈局位置的查詢請求。相對於顯示區域,以畫素為單位。其功能類似於 DOM 的 getBoundingClientRect。返回 NodesRef 對應的 SelectorQuery。

屬性型別說明idstring節點的 IDdatasetObject節點的 datasetleftnumber節點的左邊界座標rightnumber節點的右邊界座標topnumber節點的上邊界座標bottomnumber節點的下邊界座標widtheAuAUknumber節點的寬度heightnumber節點的高度

④SelectorQuery.exec(function callback)
執行所有的請求。請求結果按請求次序構成陣列,在callback的第一個引數中返回。

2) 頁面滾動監聽

  • data中初始化--tabFixed=false(表示是否固定定位)
  • 滾動條滾動距離超過了選單初始距離時,tabFixed=true開啟定位
// 監聽頁面滾動
onPageScroll: function(e) {
    let hTop = parseInt(e.scrollTop)
        // 選單是否需要定位到頂部
    if (hTop > this.data.menu_top) {
        this.setData({
            tabFixed: true
        })
    } else {
        this.setData({
            tabFixed: false
        })
    }
}

onPageScroll(Object object))
監聽使用者滑動頁面事件。

引數 Object object:

屬性 型別 說明
scrollTop Number 頁面在垂直方向已滾動的距離(單位px)

注意:請只在需要的時候才在 page 中定義此方法,不要定義空方法。以減少不必要的事件派發對渲染層-邏輯層通訊的影響。 注意:請避免在 onPageScroll 中過於頻繁的執行 setData 等引起邏輯層-渲染層通訊的操作。尤其是每次傳輸大量資料,會影響通訊耗時。

2、切換到對應區域

  • 記錄當前點選的選單並高亮
  • 獲取每個區域初始距離頁面頂部距離
  • 設定當前頁面滾動條滾動到的位置,設定過度時間

// 導航欄切換設定
setSelectType(event) {
    let index = event.currentTarget.dataset.type
    this.setData({
        tabIndex: index,})
    let arr = ['panel1_top','panel2_top','panel3_top','panel4_top']
    let _this = this
    wx.pageScrollTo({
        scrollTop: _this.data[arr[index]],duration: 500
    })
},

wx.pageScrollTo(Object object)
將頁面滾動到目標位置,支援選擇器和滾動距離兩種方式定位

屬性 型別 預設值 必填 說明
scrollTop number 滾動到頁面的目標位置,單位 px
duration number 300 滾動動畫的時長,單位 ms
selector string 選擇器 2.7.3
success function 介面呼叫成功的回撥函式
fail function 介面呼叫失敗的回撥函式
complete unction 介面呼叫結束的回撥函式(呼叫成功、失敗都會執行)

3) 滾動到某類區域時,對應區域的選單按鈕高亮

獲取初始時區域距離頂端距離

let arr = [
         { name: '.menu-nav',attr: 'menu_top',addNum: 0 },{ name: '.panel1',attr: 'panel1_top',{ name: '.panel2',attr: 'panel2_top',{ name: '.panel3',attr: 'panel3_top',{ name: '.panel4',attr: 'panel4_top',]
     arr.forEach((item,i) => {
         wx.createSelectorQuery().select(item.name).boundingClientRect(function(res) {
             let obj = {}
             if (res && res.top) {
                 obj[item.attr] = parseInt(res.top)

                 if (item.addNum) {
                     obj[item.attr] += item.addNum
                 }
                 that.setData({
                     ...obj
                 })
             }

         }).exec()

     })

滾動監聽是否超過了該區域

// 監聽頁面滾動
 onPageScroll: function(e) {
     let hThttp://www.cppcns.comop = parseInt(e.scrollTop)
     // 自動切換選單
     let tab=0
      if (hTop >= (this.data['panel4_top'] - this.data.menu_top)) {
        tab=3www.cppcns.com
     }else if (hTop >= (this.data['panel3_top'] - this.data.menu_top)){
        tab=2
     }
     else if (hTop >= (this.data['panel2_top'] - this.data.menu_top)){
         tab=1
     }
     this.setData({
         tabIndex: tab,})
 },

完整程式碼

index.

// pages/index/index.js
Page({

  /**
   * 頁面的初始資料
   */
  data: {
    tabIndex: 0,//當前處於那個選單
    menuList: ['選單1','選單2','選單3','選單4'],//導航選單
    tabFixed: false,//是否定位
    // 初始頁面距離頂部距離
    menu_top: 0,panel1_top: 0,panel2_top: 0,panel3_top: 0,panel4_top: 0,},/**
   * 生命週期函式--監聽頁面載入
   */
  onLoad: function (options) {

  },onShow:function (options){
    this.getTopDistance()
  },// 獲取距離頁面頂部高度
  getTopDistance() {
    let that = this
    let arr = [{
        name: '.menu-nav',addNum: 0
      },{
        name: '.panel1',{
        name: '.panel2',{
        name: '.panel3',{
        name: '.panel4',]
    arr.forEach((item,i) => {
      wx.createSelectorQuery().select(item.name).boundingClientRect(function (res) {
        let obj = {}
        if (res && res.top) {
          obj[item.attr] = parseInt(res.top)

          if (item.addNum) {
            obj[item.attr] += item.addNum
          }
          that.setData({
            ...obj
          })
        }

      }).exec()

    })
  },// 導航欄切換設定
  setSelectType(event) {
    let index = event.currentTarget.dataset.type
    this.setData({
      tabIndex: index,'panel4_top']
    let _this = this
    wx.pageScrollTo({
      scrollTop: _this.data[arr[index]],duration: 500
    })
  },// 監聽頁面滾動
  onPageScroll: function (e) {
    let hTop = parseInt(e.scrollTop)

    // 選單是否需要定位到頂部
    if (hTop > this.data.menu_top) {
      this.setData({
        tabFixed: true
      })
    } else {
      this.setData({
        tabFixed: false
      })
    }

    // 自動切換選單

    if (hTop >= (this.data['panel4_top'] - this.data.menu_top)) {
      this.setData({
        tabIndex: 3,})
    }else if (hTop >= (this.data['panel3_top'] - this.data.menu_top)){
      this.setData({
        tabIndex: 2,})
    }
    else if (hTop >= (this.data['panel2_top'] - this.data.menu_top)){
      this.setData({
        tabIndex: 1,})
    }else{
      this.setData({
        tabIndex: 0,})
    }
  },})

index.wxml

<view class="Main">
    <view class="head">
        我是頭部區域
    </view>
    <view class="{{tabFixed?'is-fixed':''}} menu-nav">
        <text wx:for="{{menuList}}" class="{{tabIndex==index?'is-select':''}}" bind:tap="setSelectType" data-type='{{index}}'>{{item}}</text>
        
    </view>
    <view class="content">
        <view class="panel1 panel">頁面1</view>
        <view class="panel2 panel">頁面2</view>
        <view class="panel3 panel">頁面3</view>
        <view class="panel4 panel">頁面4</view>
    </view>
</view>

index.wxss

.menu-nav {
  display: flex;
  align-items: center;
  justify-content: space-around;
  color: black;
  padding: 10px 0;
  width: 100%;
  background-color: white;
}

.is-select {
  color: red;
}

.head {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 40px;
  height: 120px;
  background-color: greenyellow;
}

.is-fixed {
  position: fixed;
  top: 0;
}

.panel {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
}

.panel1 {
  height: 800rpx;
  background-color: rebeccapurple;
}

.panel2 {
  height: 700rpx;
  background-color: blue;
}

.panel3 {
  height: 1000rpx;
  background-color: orange;
}

.panel4 {
  height: 1200rpx;
  background-color: pink;
}

到此這篇關於微信小程式-自定義選單導航(實現樓梯效果)的文章就介紹到這了,更多相關微信小程式自定義選單導航內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!