耀极客论坛

 找回密码
 立即注册
查看: 590|回复: 0

微信小程序自定义菜单导航实现楼梯效果

[复制链接]

193

主题

176

帖子

276

积分

中级会员

Rank: 3Rank: 3

积分
276
发表于 2022-5-7 01:34:46 | 显示全部楼层 |阅读模式
  在html开发中,我们可以用到a标签锚点实现,jq的动画相结合实现类似效果。在框架中vant UI框架也为我们实现了这一效果。接下来通过本文给大家介绍微信小程序自定义菜单导航实现楼梯效果,感兴趣的朋友一起看看吧
设计初衷
  在开发页面时,往往需要实现,点击页面的导航菜单页面滚动到相应位置,滚动页面实现菜单选项的高亮。在html开发中,我们可以用到a标签锚点实现,jq的动画相结合实现类似效果。在框架中vant UI框架也为我们实现了这一效果。
  微信小程序该如何实现??
效果展示
       
  • 当菜单导航滚动到页面顶部时,菜单吸顶   
  • 当点击菜单按钮时,切换到对应区域(过渡到该区域,有动画效果)   
  • 当内容区滚动到某类区域时,对应区域的菜单按钮高亮

设计思路
  1、吸顶效果的实现
       
  • 获取菜单导航距离页面顶部距离wx.createSelectorQuery()   
  • 页面滚动监听   
  • 滚动距离与菜单初始位置值比较
  1) 距离
  1. const query = wx.createSelectorQuery()
  2. query.select('.menu_nav').boundingClientRect(function(res) {
  3.     let obj = {}
  4.     if (res && res.top) {
  5.         obj[item.attr] = parseInt(res.top)
  6.     }
  7. }).exec()
复制代码
  1. ①wx.createSelectorQuery()
  2. 返回一个 SelectorQuery 对象实例。在自定义组件或包含自定义组件的页面中,应使用 this.createSelectorQuery() 来代替。
  3. ②SelectorQuery.select(string selector)
  4. 在当前页面下选择第一个匹配选择器 selector 的节点。返回一个 NodesRef 对象实例,可以用于获取节点信息。
复制代码
  selector 语法
selector类似于 CSS 的选择器,但仅支持下列语法。
属性            类型            说明                                    id            string            节点的 ID                            dataset            Object            节点的 dataset                            left            number            节点的左边界坐标                            right            number            节点的右边界坐标                            top            number            节点的上边界坐标                            bottom            number            节点的下边界坐标                            width            number            节点的宽度                            height            number            节点的高度           
  1. ③NodesRef.boundingClientRect(function callback)
  2. 添加节点的布局位置的查询请求。相对于显示区域,以像素为单位。其功能类似于 DOM 的 getBoundingClientRect。返回 NodesRef 对应的 SelectorQuery。
复制代码
  属性类型说明idstring节点的 IDdatasetObject节点的 datasetleftnumber节点的左边界坐标rightnumber节点的右边界坐标topnumber节点的上边界坐标bottomnumber节点的下边界坐标widthnumber节点的宽度heightnumber节点的高度
  1. ④SelectorQuery.exec(function callback)
  2. 执行所有的请求。请求结果按请求次序构成数组,在callback的第一个参数中返回。
复制代码
  2) 页面滚动监听
       
  • data中初始化--tabFixed=false(表示是否固定定位)   
  • 滚动条滚动距离超过了菜单初始距离时,tabFixed=true开启定位
  1. // 监听页面滚动
  2. onPageScroll: function(e) {
  3.     let hTop = parseInt(e.scrollTop)
  4.         // 菜单是否需要定位到顶部
  5.     if (hTop > this.data.menu_top) {
  6.         this.setData({
  7.             tabFixed: true
  8.         })
  9.     } else {
  10.         this.setData({
  11.             tabFixed: false
  12.         })
  13.     }
  14. }
复制代码
  onPageScroll(Object object))
监听用户滑动页面事件。
  参数 Object object:
属性            类型            说明                                    scrollTop            Number            页面在垂直方向已滚动的距离(单位px)  注意:请只在需要的时候才在 page 中定义此方法,不要定义空方法。以减少不必要的事件派发对渲染层-逻辑层通信的影响。 注意:请避免在 onPageScroll 中过于频繁的执行 setData 等引起逻辑层-渲染层通信的操作。尤其是每次传输大量数据,会影响通信耗时。
  2、切换到对应区域
       
  • 记录当前点击的菜单并高亮   
  • 获取每个区域初始距离页面顶部距离   
  • 设置当前页面滚动条滚动到的位置,设置过度时间
  1. // 导航栏切换设置
  2. setSelectType(event) {
  3.     let index = event.currentTarget.dataset.type
  4.     this.setData({
  5.         tabIndex: index,
  6.     })
  7.     let arr = ['panel1_top', 'panel2_top', 'panel3_top', 'panel4_top']
  8.     let _this = this
  9.     wx.pageScrollTo({
  10.         scrollTop: _this.data[arr[index]],
  11.         duration: 500
  12.     })
  13. },
复制代码
  wx.pageScrollTo(Object object)
将页面滚动到目标位置,支持选择器和滚动距离两种方式定位
属性            类型            默认值            必填            说明                                    scrollTop            number            无            否            滚动到页面的目标位置,单位 px                            duration            number            300            否            滚动动画的时长,单位 ms                            selector            string            无            否            选择器2.7.3                            success            function            无            否            接口调用成功的回调函数                            fail            function            无            否            接口调用失败的回调函数                            complete            unction            无            否            接口调用结束的回调函数(调用成功、失败都会执行)  3) 滚动到某类区域时,对应区域的菜单按钮高亮
  获取初始时区域距离顶端距离
  1. let arr = [
  2.          { name: '.menu-nav', attr: 'menu_top', addNum: 0 },
  3.          { name: '.panel1', attr: 'panel1_top', addNum: 0 },
  4.          { name: '.panel2', attr: 'panel2_top', addNum: 0 },
  5.          { name: '.panel3', attr: 'panel3_top', addNum: 0 },
  6.          { name: '.panel4', attr: 'panel4_top', addNum: 0 },
  7.      ]
  8.      arr.forEach((item, i) => {
  9.          wx.createSelectorQuery().select(item.name).boundingClientRect(function(res) {
  10.              let obj = {}
  11.              if (res && res.top) {
  12.                  obj[item.attr] = parseInt(res.top)
  13.                  if (item.addNum) {
  14.                      obj[item.attr] += item.addNum
  15.                  }
  16.                  that.setData({
  17.                      ...obj
  18.                  })
  19.              }
  20.          }).exec()
  21.      })
复制代码
  滚动监听是否超过了该区域
  1. // 监听页面滚动
  2. onPageScroll: function(e) {
  3.      let hTop = parseInt(e.scrollTop)
  4.      // 自动切换菜单
  5.      let tab=0
  6.       if (hTop >= (this.data['panel4_top'] - this.data.menu_top)) {
  7.         tab=3
  8.      }else if (hTop >= (this.data['panel3_top'] - this.data.menu_top)){
  9.         tab=2
  10.      }
  11.      else if (hTop >= (this.data['panel2_top'] - this.data.menu_top)){
  12.          tab=1
  13.      }
  14.      this.setData({
  15.          tabIndex: tab,
  16.      })
  17. },
复制代码
  完整代码
  index.js
  1. // pages/index/index.js
  2. Page({
  3.   /**
  4.    * 页面的初始数据
  5.    */
  6.   data: {
  7.     tabIndex: 0, //当前处于那个菜单
  8.     menuList: ['菜单1', '菜单2', '菜单3', '菜单4'], //导航菜单
  9.     tabFixed: false, //是否定位
  10.     // 初始页面距离顶部距离
  11.     menu_top: 0,
  12.     panel1_top: 0,
  13.     panel2_top: 0,
  14.     panel3_top: 0,
  15.     panel4_top: 0,
  16.   },
  17.   /**
  18.    * 生命周期函数--监听页面加载
  19.    */
  20.   onLoad: function (options) {
  21.   },
  22.   onShow:function (options){
  23.     this.getTopDistance()
  24.   },
  25.   // 获取距离页面顶部高度
  26.   getTopDistance() {
  27.     let that = this
  28.     let arr = [{
  29.         name: '.menu-nav',
  30.         attr: 'menu_top',
  31.         addNum: 0
  32.       },
  33.       {
  34.         name: '.panel1',
  35.         attr: 'panel1_top',
  36.         addNum: 0
  37.       },
  38.       {
  39.         name: '.panel2',
  40.         attr: 'panel2_top',
  41.         addNum: 0
  42.       },
  43.       {
  44.         name: '.panel3',
  45.         attr: 'panel3_top',
  46.         addNum: 0
  47.       },
  48.       {
  49.         name: '.panel4',
  50.         attr: 'panel4_top',
  51.         addNum: 0
  52.       },
  53.     ]
  54.     arr.forEach((item, i) => {
  55.       wx.createSelectorQuery().select(item.name).boundingClientRect(function (res) {
  56.         let obj = {}
  57.         if (res && res.top) {
  58.           obj[item.attr] = parseInt(res.top)
  59.           if (item.addNum) {
  60.             obj[item.attr] += item.addNum
  61.           }
  62.           that.setData({
  63.             ...obj
  64.           })
  65.         }
  66.       }).exec()
  67.     })
  68.   },
  69.   // 导航栏切换设置
  70.   setSelectType(event) {
  71.     let index = event.currentTarget.dataset.type
  72.     this.setData({
  73.       tabIndex: index,
  74.     })
  75.     let arr = ['panel1_top', 'panel2_top', 'panel3_top', 'panel4_top']
  76.     let _this = this
  77.     wx.pageScrollTo({
  78.       scrollTop: _this.data[arr[index]],
  79.       duration: 500
  80.     })
  81.   },
  82.   // 监听页面滚动
  83.   onPageScroll: function (e) {
  84.     let hTop = parseInt(e.scrollTop)
  85.     // 菜单是否需要定位到顶部
  86.     if (hTop > this.data.menu_top) {
  87.       this.setData({
  88.         tabFixed: true
  89.       })
  90.     } else {
  91.       this.setData({
  92.         tabFixed: false
  93.       })
  94.     }
  95.     // 自动切换菜单
  96.     if (hTop >= (this.data['panel4_top'] - this.data.menu_top)) {
  97.       this.setData({
  98.         tabIndex: 3,
  99.       })
  100.     }else if (hTop >= (this.data['panel3_top'] - this.data.menu_top)){
  101.       this.setData({
  102.         tabIndex: 2,
  103.       })
  104.     }
  105.     else if (hTop >= (this.data['panel2_top'] - this.data.menu_top)){
  106.       this.setData({
  107.         tabIndex: 1,
  108.       })
  109.     }else{
  110.       this.setData({
  111.         tabIndex: 0,
  112.       })
  113.     }
  114.   },
  115. })
复制代码
  index.wxml
  1. ‹view class="Main">
  2.     ‹view class="head">
  3.         我是头部区域
  4.     ‹/view>
  5.     ‹view class="{{tabFixed?'is-fixed':''}} menu-nav">
  6.         ‹text wx:for="{{menuList}}" class="{{tabIndex==index?'is-select':''}}" bind:tap="setSelectType" data-type='{{index}}'>{{item}}‹/text>
  7.         
  8.     ‹/view>
  9.     ‹view class="content">
  10.         ‹view class="panel1 panel">页面1‹/view>
  11.         ‹view class="panel2 panel">页面2‹/view>
  12.         ‹view class="panel3 panel">页面3‹/view>
  13.         ‹view class="panel4 panel">页面4‹/view>
  14.     ‹/view>
  15. ‹/view>
复制代码
  index.wxss
  1. .menu-nav {
  2.   display: flex;
  3.   align-items: center;
  4.   justify-content: space-around;
  5.   color: black;
  6.   padding: 10px 0;
  7.   width: 100%;
  8.   background-color: white;
  9. }
  10. .is-select {
  11.   color: red;
  12. }
  13. .head {
  14.   display: flex;
  15.   align-items: center;
  16.   justify-content: center;
  17.   font-size: 40px;
  18.   height: 120px;
  19.   background-color: greenyellow;
  20. }
  21. .is-fixed {
  22.   position: fixed;
  23.   top: 0;
  24. }
  25. .panel {
  26.   display: flex;
  27.   align-items: center;
  28.   justify-content: center;
  29.   font-size: 20px;
  30. }
  31. .panel1 {
  32.   height: 800rpx;
  33.   background-color: rebeccapurple;
  34. }
  35. .panel2 {
  36.   height: 700rpx;
  37.   background-color: blue;
  38. }
  39. .panel3 {
  40.   height: 1000rpx;
  41.   background-color: orange;
  42. }
  43. .panel4 {
  44.   height: 1200rpx;
  45.   background-color: pink;
  46. }
复制代码
  到此这篇关于微信小程序-自定义菜单导航(实现楼梯效果)的文章就介绍到这了,更多相关微信小程序自定义菜单导航内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|耀极客论坛 ( 粤ICP备2022052845号-2 )|网站地图

GMT+8, 2022-11-28 20:03 , Processed in 0.068683 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表