国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

微信小程序 特效菜單抽屜效果實例代碼

2019-11-19 18:00:18
字體:
來源:轉載
供稿:網友

實現效果圖:

抽屜菜單是app上常見的菜單設計方式,典型的抽屜菜單如下圖所示

下面展示如何基于微信小程序實現抽屜菜單,最終效果如下圖所示: 

頁面包含一個主頁和抽屜菜單頁,為了實現滑動效果,頁面采用absolute布局,代碼如下 

index.wxml

<view id='id-main-page' class='main-page' animation='{{animationData}}' style='left:{{mainPageLeft}}rpx;' bindtouchstart='onMainPageTouchstart' catchtouchmove='onMainPageTouchmove' bindtouchend='onMainPageTouchend' bindtap='onMainPageTap'> <view class="userinfo">  <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>  <text class="userinfo-nickname">{{userInfo.nickName}}</text> </view></view><view class='drawer-menu' animation='{{animationData}}' style='left:{{drawerMenuLeft}}rpx;'> <view class="userinfo">  <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>  <text class="userinfo-nickname">{{userInfo.nickName2}}</text> </view></view>

index.wxss

.main-page { width:100%; height:2000rpx; position: absolute; top: 0; left: 0; padding: 200rpx 0;}.drawer-menu { width: 800rpx; height:2000rpx; position: absolute; top: 0; left: -800rpx; padding: 200rpx 0; background: rgba(22, 22, 22, 1); z-index: 800;}

程序綁定了主頁的touch事件和tap事件,并且使用catchtouchmove阻止了move事件的傳遞,因為在真機環境下頁面會自動響應滑動事件,注意不要catch startend事件,這會導致無法觸發tap事件。

首先定義一些數據來記錄滑動過程和狀態

 drawerMenuMoveData: {  check: false,  //是否觸發滑動操作  state:0,  //0:初始狀態 1:菜單彈出中狀態 2:菜單彈入狀態中 3:菜單彈出狀態  firstTouchX:0, //首次觸摸X坐標值  touchCheckX:60, //觸發滑動的觸摸X  moveX:0,  // 滑動操作橫向的移動距離  maxMoveX: (app.globalData.deviceInfo.windowWidth - 60), //抽屜菜單最大移動距離  lastTranlateX: 0 //上次動畫效果的平移距離,用于校準left值 },

之后就是滑動事件的響應處理 

touchstart事件,首先判斷當前狀態,然后根據觸摸位置判斷是否激活滑動狀態

 onMainPageTouchstart: function(e) {  var data = this.drawerMenuMoveData;  var clientX = e.touches[0].clientX;  //初識狀態  if (data.state === 0) {   if (clientX <= data.touchCheckX && clientX > 20) {    data.check = true;    data.state = 1;    data.firstTouchX = clientX;   }  }  //菜單彈出狀態  else if (data.state === 3) {   if (clientX >= data.maxMoveX) {    data.check = true;    data.state = 2;    data.firstTouchX = clientX;   }  }  },

touchmove 事件,首先判斷是否處于滑動狀態,之后根據當前模式來計算主頁和菜單頁的left值來產生滑動效果

 onMainPageTouchmove: function(e) {  var data = this.drawerMenuMoveData;  var pixelRatio = app.globalData.deviceInfo.pixelRatio;  if (data.check) {   var mainPageLeft = 0, drawerMenuLeft = 0;   var moveX = e.touches[0].clientX - data.firstTouchX;   if (data.state === 1)   {    //處理邊界狀態    if (moveX < 0) {     moveX = 0;    }    if (moveX > data.maxMoveX) {     moveX = data.maxMoveX;    }    if (moveX >= 0 && moveX <= data.maxMoveX) {     data.moveX = moveX;     moveX = moveX - data.lastTranlateX;     //px轉為rpx     moveX = moveX * pixelRatio;     mainPageLeft = moveX;     drawerMenuLeft = -800 + moveX;    }   }   else if (data.state === 2) {    //處理邊界狀態    if (moveX > 0) {     moveX = 0;    }    if (moveX < -data.maxMoveX) {     moveX = -data.maxMoveX;     }    if (moveX <= 0 && moveX >= -data.maxMoveX) {     data.moveX = moveX;     moveX = moveX - data.lastTranlateX;     //px轉為rpx     moveX = moveX * pixelRatio;     var maxMoveX = data.maxMoveX * pixelRatio;     mainPageLeft = maxMoveX + moveX;     drawerMenuLeft = maxMoveX -800 + moveX;    }   }   this.setData({mainPageLeft: mainPageLeft,           drawerMenuLeft: drawerMenuLeft});  } },

touchend事件 根據滑動的距離來判斷菜單是否彈出,并創建滑動動畫

 onMainPageTouchend: function(e) {  var data = this.drawerMenuMoveData;  if (!data.check) {   return;  }  data.check = false;  data.firstTouchX = 0;  var moveX = data.moveX;  data.moveX = 0;  var animation = wx.createAnimation({duration: 100});  var translateX = 0;  var mainPageLeft = 0;  var windowWidth = app.globalData.deviceInfo.windowWidth;  if (data.state === 1)  {   if (moveX === 0 || moveX === data.maxMoveX) {    data.state = (moveX === 0) ? 0 : 3;    return;   }   mainPageLeft = moveX;   //滑動距離是否超過窗口寬度一半   if (mainPageLeft > (windowWidth / 2)) {    translateX = data.maxMoveX - moveX;    data.state = 3;   }   else {    translateX = -moveX;    data.state = 0;   }  }   else if (data.state === 2) {   if (moveX === 0 || moveX === -data.maxMoveX) {    data.state = (moveX === 0) ? 3 : 0;    return;   }   //滑動距離是否超過窗口寬度一半   mainPageLeft = data.maxMoveX + moveX   if (mainPageLeft > (windowWidth / 2)) {    translateX = -moveX;    data.state = 3;   }   else {    translateX = -mainPageLeft;    data.state = 0;   }  }  translateX += data.lastTranlateX;  data.lastTranlateX = translateX;  animation.translateX(translateX).step();  this.setData({   animationData:animation.export()  }); },

tap事件, 如果當前是彈出狀態,則將菜單彈回

 onMainPageTap: function(e) {  var data = this.drawerMenuMoveData;  if (data.state !== 3) {   return;  }  data.state = 0;  var translateX = -data.maxMoveX;  translateX += data.lastTranlateX;  data.lastTranlateX = translateX;  var animation = wx.createAnimation({duration: 100});  animation.translateX(translateX).step();  this.setData({   animationData:animation.export()  }); }

總體邏輯并不復雜,主要是做好狀態判斷和坐標運算,但有些問題需要注意

1: 微信小程序提供了rpx單位用于適配設備,但是各種滑動事件和動畫的單位通常是px,因此需要進行轉換,轉換方法為 rpx = px * pixelRatio,其中pixelRatio可以通過 wx.getSystemInfoSync()獲取

2: 當對組件使用通過wx.createAnimation 創建的動畫時,小程序框架會給組件添加transform屬性,其中translateX值會和left屬性相互作用,因此計算left值時需要處理translateX的值。

3: 由于在真機環境下,頁面左滑(初始觸摸點在左側邊界時)默認行為是返回上一頁或退出小程序(取決與是否是第一級頁面), 抽屜菜單會和該行為發生沖突。

另外目前還不支持swiper操作,后續有機會再補上吧。

源碼下載:http://xiazai.VeVB.COm/201701/yuanma/wx-drawermenu-master(VeVB.COm).rar

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 平江县| 方正县| 丹巴县| 禄劝| 东乌珠穆沁旗| 法库县| 昭觉县| 黔江区| 海南省| 江川县| 利辛县| 东莞市| 岳阳县| 文山县| 满城县| 北宁市| 榆树市| 新昌县| 廉江市| 大英县| 贞丰县| 天全县| 渭源县| 屏山县| 双牌县| 连云港市| 湘潭县| 聂荣县| 镇江市| 英吉沙县| 深州市| 湘阴县| 宝鸡市| 响水县| 庆元县| 固镇县| 千阳县| 盘山县| 贺州市| 东宁县| 深圳市|