轻源码

  • QingYuanMa.com
  • 全球最大的互联网技术和资源下载平台
搜索
一起源码网 门户 终极进阶 查看主题

微信小程序实战开发教程-抽屉菜单

发布者: xiaomen2 | 发布时间: 2017-2-18 18:47| 查看数: 9496| 评论数: 1|帖子模式

作者:crazytea,来自授权地址

抽屉菜单是app上常见的菜单设计方式,典型的抽屉菜单如下图所示

下面展示如何基于微信小程序实现抽屉菜单,最终效果如下图所示: 

页面包含一个主页和抽屉菜单页,为了实现滑动效果,页面采用absolute布局,代码如下 
index.wxml

  1. <view id='id-main-page' class='main-page' animation='{{animationData}}' style='left:{{mainPageLeft}}rpx;'
  2. bindtouchstart='onMainPageTouchstart' catchtouchmove='onMainPageTouchmove' bindtouchend='onMainPageTouchend' bindtap='onMainPageTap'>
  3. <view class="userinfo">
  4. <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
  5. <text class="userinfo-nickname">{{userInfo.nickName}}</text>
  6. </view>
  7. </view>
  8. <view class='drawer-menu' animation='{{animationData}}' style='left:{{drawerMenuLeft}}rpx;'>
  9. <view class="userinfo">
  10. <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
  11. <text class="userinfo-nickname">{{userInfo.nickName2}}</text>
  12. </view>
  13. </view>

index.wxss

  1. .main-page {
  2. width:100%;
  3. height:2000rpx;
  4. position: absolute;
  5. top: 0;
  6. left: 0;
  7. padding: 200rpx 0;
  8. }
  9. .drawer-menu {
  10. width: 800rpx;
  11. height:2000rpx;
  12. position: absolute;
  13. top: 0;
  14. left: -800rpx;
  15. padding: 200rpx 0;
  16. background: rgba(22, 22, 22, 1);
  17. z-index: 800;
  18. }

程序绑定了主页的touch事件和tap事件,并且使用catchtouchmove阻止了move事件的传递,因为在真机环境下页面会自动响应滑动事件,注意不要catch startend事件,这会导致无法触发tap事件。

首先定义一些数据来记录滑动过程和状态

  1. drawerMenuMoveData: {
  2. check: false, //是否触发滑动操作
  3. state:0, //0:初始状态 1:菜单弹出中状态 2:菜单弹入状态中 3:菜单弹出状态
  4. firstTouchX:0, //首次触摸X坐标值
  5. touchCheckX:60, //触发滑动的触摸X
  6. moveX:0, // 滑动操作横向的移动距离
  7. maxMoveX: (app.globalData.deviceInfo.windowWidth - 60), //抽屉菜单最大移动距离
  8. lastTranlateX: 0 //上次动画效果的平移距离,用于校准left
  9. },

之后就是滑动事件的响应处理 
touchstart事件,首先判断当前状态,然后根据触摸位置判断是否激活滑动状态

  1. onMainPageTouchstart: function(e) {
  2. var data = this.drawerMenuMoveData;
  3. var clientX = e.touches[0].clientX;
  4. //初识状态
  5. if (data.state === 0) {
  6. if (clientX <= data.touchCheckX && clientX > 20) {
  7. data.check = true;
  8. data.state = 1;
  9. data.firstTouchX = clientX;
  10. }
  11. }
  12. //菜单弹出状态
  13. else if (data.state === 3) {
  14. if (clientX >= data.maxMoveX) {
  15. data.check = true;
  16. data.state = 2;
  17. data.firstTouchX = clientX;
  18. }
  19. }
  20. },

touchmove 事件,首先判断是否处于滑动状态,之后根据当前模式来计算主页和菜单页的left值来产生滑动效果

  1. onMainPageTouchmove: function(e) {
  2. var data = this.drawerMenuMoveData;
  3. var pixelRatio = app.globalData.deviceInfo.pixelRatio;
  4. if (data.check) {
  5. var mainPageLeft = 0, drawerMenuLeft = 0;
  6. var moveX = e.touches[0].clientX - data.firstTouchX;
  7. if (data.state === 1)
  8. {
  9. //处理边界状态
  10. if (moveX < 0) {
  11. moveX = 0;
  12. }
  13. if (moveX > data.maxMoveX) {
  14. moveX = data.maxMoveX;
  15. }
  16. if (moveX >= 0 && moveX <= data.maxMoveX) {
  17. data.moveX = moveX;
  18. moveX = moveX - data.lastTranlateX;
  19. //px转为rpx
  20. moveX = moveX * pixelRatio;
  21. mainPageLeft = moveX;
  22. drawerMenuLeft = -800 + moveX;
  23. }
  24. }
  25. else if (data.state === 2) {
  26. //处理边界状态
  27. if (moveX > 0) {
  28. moveX = 0;
  29. }
  30. if (moveX < -data.maxMoveX) {
  31. moveX = -data.maxMoveX;
  32. }
  33. if (moveX <= 0 && moveX >= -data.maxMoveX) {
  34. data.moveX = moveX;
  35. moveX = moveX - data.lastTranlateX;
  36. //px转为rpx
  37. moveX = moveX * pixelRatio;
  38. var maxMoveX = data.maxMoveX * pixelRatio;
  39. mainPageLeft = maxMoveX + moveX;
  40. drawerMenuLeft = maxMoveX -800 + moveX;
  41. }
  42. }
  43. this.setData({mainPageLeft: mainPageLeft,
  44. drawerMenuLeft: drawerMenuLeft});
  45. }
  46. },

touchend事件 根据滑动的距离来判断菜单是否弹出,并创建滑动动画

  1. onMainPageTouchend: function(e) {
  2. var data = this.drawerMenuMoveData;
  3. if (!data.check) {
  4. return;
  5. }
  6. data.check = false;
  7. data.firstTouchX = 0;
  8. var moveX = data.moveX;
  9. data.moveX = 0;
  10. var animation = wx.createAnimation({duration: 100});
  11. var translateX = 0;
  12. var mainPageLeft = 0;
  13. var windowWidth = app.globalData.deviceInfo.windowWidth;
  14. if (data.state === 1)
  15. {
  16. if (moveX === 0 || moveX === data.maxMoveX) {
  17. data.state = (moveX === 0) ? 0 : 3;
  18. return;
  19. }
  20. mainPageLeft = moveX;
  21. //滑动距离是否超过窗口宽度一半
  22. if (mainPageLeft > (windowWidth / 2)) {
  23. translateX = data.maxMoveX - moveX;
  24. data.state = 3;
  25. }
  26. else {
  27. translateX = -moveX;
  28. data.state = 0;
  29. }
  30. }
  31. else if (data.state === 2) {
  32. if (moveX === 0 || moveX === -data.maxMoveX) {
  33. data.state = (moveX === 0) ? 3 : 0;
  34. return;
  35. }
  36. //滑动距离是否超过窗口宽度一半
  37. mainPageLeft = data.maxMoveX + moveX
  38. if (mainPageLeft > (windowWidth / 2)) {
  39. translateX = -moveX;
  40. data.state = 3;
  41. }
  42. else {
  43. translateX = -mainPageLeft;
  44. data.state = 0;
  45. }
  46. }
  47. translateX += data.lastTranlateX;
  48. data.lastTranlateX = translateX;
  49. animation.translateX(translateX).step();
  50. this.setData({
  51. animationData:animation.export()
  52. });
  53. },

tap事件, 如果当前是弹出状态,则将菜单弹回

  1. onMainPageTap: function(e) {
  2. var data = this.drawerMenuMoveData;
  3. if (data.state !== 3) {
  4. return;
  5. }
  6. data.state = 0;
  7. var translateX = -data.maxMoveX;
  8. translateX += data.lastTranlateX;
  9. data.lastTranlateX = translateX;
  10. var animation = wx.createAnimation({duration: 100});
  11. animation.translateX(translateX).step();
  12. this.setData({
  13. animationData:animation.export()
  14. });
  15. }

总体逻辑并不复杂,主要是做好状态判断和坐标运算,但有些问题需要注意

1: 微信小程序提供了rpx单位用于适配设备,但是各种滑动事件和动画的单位通常是px,因此需要进行转换,转换方法为 rpx = px * pixelRatio,其中pixelRatio可以通过 wx.getSystemInfoSync()获取

2: 当对组件使用通过wx.createAnimation 创建的动画时,小程序框架会给组件添加transform属性,其中translateX值会和left属性相互作用,因此计算left值时需要处理translateX的值。

3: 由于在真机环境下,页面左滑(初始触摸点在左侧边界时)默认行为是返回上一页或退出小程序(取决与是否是第一级页面), 抽屉菜单会和该行为发生冲突。

另外目前还不支持swiper操作,后续有机会再补上吧。

源码地址::

源码下载:wx-drawermenu-master.zip

最新评论

zzzz 发表于 2022-4-26 10:42
手机电影网站源代码

轻源码让程序更轻更快

QingYuanMa.com

工作时间 周一至周六 8:00-17:30

侵权处理

客服QQ点击咨询

关注抖音号

定期抽VIP

Copyright © 2016-2021 https://www.171739.xyz/ 滇ICP备13200218号

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