微信小程序自定義菜單導航實現樓梯效果
設計初衷
在開發(fā)頁面時,往往需要實現,點擊頁面的導航菜單頁面滾動到相應位置,滾動頁面實現菜單選項的高亮。在html開發(fā)中,我們可以用到a標簽錨點實現,jq的動畫相結合實現類似效果。在框架中vant UI框架也為我們實現了這一效果。
微信小程序該如何實現??
效果展示
- 當菜單導航滾動到頁面頂部時,菜單吸頂
- 當點擊菜單按鈕時,切換到對應區(qū)域(過渡到該區(qū)域,有動畫效果)
- 當內容區(qū)滾動到某類區(qū)域時,對應區(qū)域的菜單按鈕高亮
設計思路
1、吸頂效果的實現
- 獲取菜單導航距離頁面頂部距離
wx.createSelectorQuery()
- 頁面滾動監(jiān)聽
- 滾動距離與菜單初始位置值比較
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 的節(jié)點。返回一個 NodesRef 對象實例,可以用于獲取節(jié)點信息。
selector 語法
selector類似于 CSS 的選擇器,但僅支持下列語法。
屬性 | 類型 | 說明 |
---|---|---|
id | string | 節(jié)點的 ID |
dataset | Object | 節(jié)點的 dataset |
left | number | 節(jié)點的左邊界坐標 |
right | number | 節(jié)點的右邊界坐標 |
top | number | 節(jié)點的上邊界坐標 |
bottom | number | 節(jié)點的下邊界坐標 |
width | number | 節(jié)點的寬度 |
height | number | 節(jié)點的高度 |
③NodesRef.boundingClientRect(function callback)
添加節(jié)點的布局位置的查詢請求。相對于顯示區(qū)域,以像素為單位。其功能類似于 DOM 的 getBoundingClientRect。返回 NodesRef 對應的 SelectorQuery。
屬性類型說明idstring節(jié)點的 IDdatasetObject節(jié)點的 datasetleftnumber節(jié)點的左邊界坐標rightnumber節(jié)點的右邊界坐標topnumber節(jié)點的上邊界坐標bottomnumber節(jié)點的下邊界坐標widthnumber節(jié)點的寬度heightnumber節(jié)點的高度
④SelectorQuery.exec(function callback)
執(zhí)行所有的請求。請求結果按請求次序構成數組,在callback的第一個參數中返回。
2) 頁面滾動監(jiān)聽
- data中初始化--
tabFixed=false
(表示是否固定定位) - 滾動條滾動距離超過了菜單初始距離時,
tabFixed=true
開啟定位
// 監(jiān)聽頁面滾動 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))
監(jiān)聽用戶滑動頁面事件。
參數 Object object:
屬性 | 類型 | 說明 |
---|---|---|
scrollTop | Number | 頁面在垂直方向已滾動的距離(單位px) |
注意:請只在需要的時候才在 page 中定義此方法,不要定義空方法。以減少不必要的事件派發(fā)對渲染層-邏輯層通信的影響。 注意:請避免在 onPageScroll 中過于頻繁的執(zhí)行 setData 等引起邏輯層-渲染層通信的操作。尤其是每次傳輸大量數據,會影響通信耗時。
2、切換到對應區(qū)域
- 記錄當前點擊的菜單并高亮
- 獲取每個區(qū)域初始距離頁面頂部距離
- 設置當前頁面滾動條滾動到的位置,設置過度時間
// 導航欄切換設置 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 | 無 | 否 | 接口調用結束的回調函數(調用成功、失敗都會執(zhí)行) |
3) 滾動到某類區(qū)域時,對應區(qū)域的菜單按鈕高亮
獲取初始時區(qū)域距離頂端距離
let arr = [ { name: '.menu-nav', attr: 'menu_top', addNum: 0 }, { name: '.panel1', attr: 'panel1_top', addNum: 0 }, { name: '.panel2', attr: 'panel2_top', addNum: 0 }, { name: '.panel3', attr: 'panel3_top', addNum: 0 }, { name: '.panel4', attr: 'panel4_top', addNum: 0 }, ] 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() })
滾動監(jiān)聽是否超過了該區(qū)域
// 監(jiān)聽頁面滾動 onPageScroll: function(e) { let hTop = parseInt(e.scrollTop) // 自動切換菜單 let tab=0 if (hTop >= (this.data['panel4_top'] - this.data.menu_top)) { tab=3 }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.js
// 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, }, /** * 生命周期函數--監(jiān)聽頁面加載 */ onLoad: function (options) { }, onShow:function (options){ this.getTopDistance() }, // 獲取距離頁面頂部高度 getTopDistance() { let that = this let arr = [{ name: '.menu-nav', attr: 'menu_top', addNum: 0 }, { name: '.panel1', attr: 'panel1_top', addNum: 0 }, { name: '.panel2', attr: 'panel2_top', addNum: 0 }, { name: '.panel3', attr: 'panel3_top', addNum: 0 }, { name: '.panel4', attr: 'panel4_top', addNum: 0 }, ] 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, }) let arr = ['panel1_top', 'panel2_top', 'panel3_top', 'panel4_top'] let _this = this wx.pageScrollTo({ scrollTop: _this.data[arr[index]], duration: 500 }) }, // 監(jiān)聽頁面滾動 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"> 我是頭部區(qū)域 </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; }
到此這篇關于微信小程序-自定義菜單導航(實現樓梯效果)的文章就介紹到這了,更多相關微信小程序自定義菜單導航內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
javascript+html5實現繪制圓環(huán)的方法
這篇文章主要介紹了javascript+html5實現繪制圓環(huán)的方法,實例分析了javascript實現html5基于canvas繪制圓環(huán)的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07微信小程序 多行文本顯示...+顯示更多按鈕和收起更多按鈕功能
這篇文章主要介紹了微信小程序多行文本顯示...+顯示更多按鈕和收起更多按鈕,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-09-09JavaScript設計模式之原型模式分析【ES5與ES6】
這篇文章主要介紹了JavaScript設計模式之原型模式,簡單描述了原型模式的概念、原理,并結合實例形式分析了ES5與ES6實現原型模式的相關操作技巧,需要的朋友可以參考下2018-07-07