Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >微信小程序-自定义菜单导航(实现楼梯效果)

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

作者头像
落寞的鱼丶
发布于 2022-02-28 10:12:26
发布于 2022-02-28 10:12:26
1.8K00
代码可运行
举报
文章被收录于专栏:afjhahfhahajkafjhahfhahajk
运行总次数:0
代码可运行

设计初衷

在开发页面时,往往需要实现,点击页面的导航菜单页面滚动到相应位置,滚动页面实现菜单选项的高亮。在html开发中,我们可以用到a标签锚点实现,jq的动画相结合实现类似效果。在框架中vant UI框架也为我们实现了这一效果。

微信小程序该如何实现??

效果展示

  1. 当菜单导航滚动到页面顶部时,菜单吸顶
  2. 当点击菜单按钮时,切换到对应区域(过渡到该区域,有动画效果)
  3. 当内容区滚动到某类区域时,对应区域的菜单按钮高亮

设计思路

1、吸顶效果的实现
  • 获取菜单导航距离页面顶部距离wx.createSelectorQuery()
  • 页面滚动监听
  • 滚动距离与菜单初始位置值比较
1) 距离
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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类似于 CSS 的选择器,但仅支持下列语法。

  • ID选择器:#the-id
  • class选择器(可以连续指定多个):.a-class.another-class
  • 子元素选择器:.the-parent > .the-child
  • 后代选择器:.the-ancestor .the-descendant
  • 跨自定义组件的后代选择器:.the-ancestor >>> .the-descendant
  • 多选择器的并集:#a-node, .some-other-nodes

③NodesRef.boundingClientRect(function callback) 添加节点的布局位置的查询请求。相对于显示区域,以像素为单位。其功能类似于 DOM 的 getBoundingClientRect。返回 NodesRef 对应的 SelectorQuery。

属性

类型

说明

id

string

节点的 ID

dataset

Object

节点的 dataset

left

number

节点的左边界坐标

right

number

节点的右边界坐标

top

number

节点的上边界坐标

bottom

number

节点的下边界坐标

width

number

节点的宽度

height

number

节点的高度

④SelectorQuery.exec(function callback) 执行所有的请求。请求结果按请求次序构成数组,在callback的第一个参数中返回。

2) 页面滚动监听
  • data中初始化--tabFixed=false(表示是否固定定位)
  • 滚动条滚动距离超过了菜单初始距离时,tabFixed=true开启定位
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 监听页面滚动
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、切换到对应区域
  1. 记录当前点击的菜单并高亮
  2. 获取每个区域初始距离页面顶部距离
  3. 设置当前页面滚动条滚动到的位置,设置过度时间
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 导航栏切换设置
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) 滚动到某类区域时,对应区域的菜单按钮高亮
  1. 获取初始时区域距离顶端距离 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() })
  2. 滚动监听是否超过了该区域 // 监听页面滚动 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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 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',
        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
    })
  },
  // 监听页面滚动
  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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.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;
}

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
微信小程序仿APP section header 悬停效果
在onReady方法中,查询section-header节点并拿到该节点此时距离当前顶部的距离
韦弦zhy
2018/09/11
2.1K0
微信小程序仿APP section header 悬停效果
微信小程序 简单的实现左右内容联动
超级小的大杯柠檬水
2023/06/18
6600
微信小程序 简单的实现左右内容联动
微信小程序锚点选择导航栏
<view class='box'> <scroll-view scroll-y scroll-with-animation style="width:25%"> <view
明知山
2020/09/02
1.2K0
小程序之图片懒加载
懒加载,前端人都知道的一种性能优化方式,简单的来说,只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。
前端黑板报
2018/12/24
1.1K0
微信小程序中实现吸顶效果(流畅、不卡顿)
最开始的时候,在小程序中实现吸顶效果,开发工具看起来还挺好的,但是在真机上就会有问题了。 原因是我不停的去 setData 会导致操作反馈延迟严重,无法及时将操作处理结果及时传递到视图层。 后面就对代码进行了调整,避免不停的去setData 效果图 吸顶前 吸顶后 代码部分 wxml <view style="width: 90%; height: 300rpx; background: #f0f0f0; margin: 30rpx auto;"></view> <view style="wi
别盯着我的名字看
2022/06/09
2.6K0
微信小程序中实现吸顶效果(流畅、不卡顿)
小程序scroll-view滚动时高亮对应区域的吸顶tab项
记一下scroll-view的使用 滚动时,区域元素出现在屏幕上,对应的tab项目高亮 代码: wxml: <view class="sticky-menu" hidden="{{appear}}"
薛定喵君
2019/11/06
2.5K0
微信小程序解决ios页面上推问题
相信大家写原生小程序都遇到过一个问题,当输入框聚焦键盘弹起时,页面会自动上推,使得输入框刚好位于键盘之上,在安卓中推动的只是内容,但在ios中,推动的是整个页面,导致导航栏被推出屏幕外,如下:
maureen
2023/03/23
5.7K0
微信小程序导航栏页面滑动切换
<view class="banner"> <scroll-view scroll-x="true" scroll-with-animation="true" scroll-into-view="
明知山
2020/09/17
5.4K1
微信小程序导航栏页面滑动切换
微信小程序如何获取组件实际高度
viewscroll-view scroll-x scroll-with-animation scroll-left="{{menuIndex}}" style="height: 100px; width:100%;"view id='#haha' class='all' style='width:{{menuWidth}}px;'block wx:key="lists" wx:for="{{li ...
疯狂的小程序
2018/01/22
3.6K0
微信小程序如何获取组件实际高度
【愚公系列】2022年02月 微信小程序-页面生命周期
注册小程序中的一个页面。接受一个 Object 类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。
愚公搬代码
2022/12/01
5340
微信小程序实现A-Z快捷导航
效果 代码 slidebar.wxml <view id="s-bar" class="slidebar" bindtouchstart="_onTouchStart" bindtouchmove=
用户5997198
2019/11/15
1.4K0
微信小程序实现A-Z快捷导航
小程序项目开发实战:打造一款微信点餐小程序
随着微信小程序的流行,越来越多的开发者开始涉足小程序开发。本篇文章将带领读者通过一个实际的案例,一步步开发一款微信点餐小程序。我们将从项目的准备工作开始,逐步介绍小程序开发的各个方面,包括页面设计与布局、数据绑定与交互逻辑、页面跳转与路由、数据请求与展示、用户授权与登录、性能优化与调试技巧,以及最后的小程序上线与发布。
海拥
2023/07/05
3.6K0
【愚公系列】2022年08月 微信小程序-slider滑动选择器详解
文章目录 前言 一、slider滑动选择器 1.wxml 2.js 3.效果 二、自定义滑动选择器 1.组件的封装 2.组件的使用 ---- 前言 小程序中滑动选择器相关属性如下: 属性 类型 默认值 必填 说明 最低版本 min number 0 否 最小值 1.0.0 max number 100 否 最大值 1.0.0 step number 1 否 步长,取值必须大于 0,并且可被(max - min)整除 1.0.0 disabled boolean false 否 是否禁用 1.0.0 valu
愚公搬代码
2022/09/27
1.6K1
【愚公系列】2022年08月 微信小程序-slider滑动选择器详解
微信小程序展开全文
设置130为临界值,是试了3行基本不超过120rpx,4行基本大于140rpx,取了个中间值
韦弦zhy
2018/09/11
1.6K0
微信小程序展开全文
小程序 - 如何自定义导航栏
setStatusBarHeight、setNavBar这两个方法最好写到app.js中,获取好放在app.globalData中,这两个高度可能不止自定义导航栏需要用到。
WahFung
2020/08/24
1.4K0
小程序 - 如何自定义导航栏
如何让10万条数据的小程序列表如丝般顺滑
https://juejin.cn/post/6966904317148299271
@超人
2021/07/05
6980
如何让10万条数据的小程序列表如丝般顺滑
性能测试之微信小程序websocket协议
最近复习性能测试,也想看看小程序聊天页面中的信息底层是怎么实现的,今天试着写了写。
高楼Zee
2019/12/27
1K0
性能测试之微信小程序websocket协议
小程序tab实现之swiper自适应高度并记录滚动位置
移动端中需要使用swiper插件实现tab切换和手势滑动的,在各种APP上我们可以很常见,但在小程序上实现这个看起来有点难,因为swiper插件滑动到下一屏的时候位置总是会回到跟上一屏相同的位置。我记得微信刚出来不久,有一个这样子的需求,那时候是另外一个同事在跟,跟我说到过这个功能无法实现。最近我也接到这个需求,于是我认真的看了一下微信组件文档,发现swiper+scroll-view组件结合是可以实现这个功能。
前端开发博客
2020/11/04
2.2K0
小程序tab实现之swiper自适应高度并记录滚动位置
【微信小程序】---- 监听页面停止滚动
1. 场景需求 页面页脚部分有一面积高300px的浮窗,遮挡页面很严重,但是浮窗的内容又很重要;业务需求,当页面滚动的时候,浮窗隐藏,页面停止滚动的时候浮窗显示! 2. 需求分析 监听页面滚动停止动作,没有这类监听的函数,但是我们可以监听页面滚动 onPageScroll; 显示和隐藏浮窗,这一步很好操作,直接一 Boolean 变量 false or true,就能解决; 3. 解决思路 如何在页面滚动监听的函数中知道页面停止滚动? 1.1 方法一:对比前后两次的滚动变量 scrollTop; 1.
Rattenking
2022/01/06
2.9K0
微信小程序实现各种特效实例
写在前面 最近在负责一个微信小程序的前端以及前后端接口的对接的项目,整体上所有页面的布局我都已经搭建完成,里面有一些常用的特效,总结一下,希望对大家和我都能有所帮助 实例1:滚动tab选项卡 先看一下
okaychen
2018/01/05
4.1K3
微信小程序实现各种特效实例
推荐阅读
相关推荐
微信小程序仿APP section header 悬停效果
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验