微信小程序 触控事件

2018-03-14 14:21:01 脚本之家  点击量: 评论 (0)
》》》什么是事件事件是视图层到逻辑层的通讯方式。事件可以将用户的行为反馈到逻辑层进行处理。事件可以绑定在组件上,当达到触发事件,就

》》》什么是事件

  1. 事件是视图层到逻辑层的通讯方式。
  2. 事件可以将用户的行为反馈到逻辑层进行处理。
  3. 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
  4. 事件对象可以携带额外信息,如id, dataset, touches。

事件的使用方式

在组件中绑定一个事件处理函数。

如bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。

<view id="tapTest" data-hi="MINA" bindtap="tapName"> Click me! </view> 

在相应的Page定义中写上相应的事件处理函数,参数是event。

[html] view plain copy
 
  1. Page({  
  2.  tapName: function(event) {  
  3.  console.log(event)  
  4.  }  
  5. })  

 

可以看到log出来的信息大致如下:

[html] view plain copy
 
  1. {  
  2. "type":"tap",  
  3. "timeStamp": 1252,  
  4. "target": {  
  5.  "id":"tapTest",  
  6.  "offsetLeft": 0,  
  7.  "offsetTop": 0,  
  8.  "dataset": {  
  9.  "hi":"MINA"  
  10.  }  
  11. },  
  12. "currentTarget": {  
  13.  "id":"tapTest",  
  14.  "offsetLeft": 0,  
  15.  "offsetTop": 0,  
  16.  "dataset": {  
  17.  "hi":"MINA"  
  18.  }  
  19. },  
  20. "touches": [{  
  21.  "pageX": 30,  
  22.  "pageY": 12,  
  23.  "clientX": 30,  
  24.  "clientY": 12,  
  25.  "screenX": 112,  
  26.  "screenY": 151  
  27. }],  
  28. "detail": {  
  29.  "x": 30,  
  30.  "y": 12  
  31. }  
  32. }  

 

事件详解

事件分类

事件分为冒泡事件和非冒泡事件:

冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。

非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。

》》》事件分类

  1. touchstart 手指触摸
  2. touchmove 手指触摸后移动
  3. touchcancel 手指触摸动作被打断,如弹窗和来电提醒
  4. touchend 手指触摸动作结束
  5. tap 手指触摸后离开
  6. longtap 手指触摸后后,超过350ms离开

》》》事件绑定

事件绑定的写法同组件的属性,以 key、value 的形式。

  1. key 以bind或catch开头,然后跟上事件的类型,如bindtap, catchtouchstart
  2. value 是一个字符串,需要在对应的 Page 中定义同名的函数。不然当触发事件的时候会报错。 bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡。

上面简单介绍了小程序事件基础,是时候彰显"事件"的威力:

  1. 单击(tap)
  2. 双击(dbtap)
  3. 长按(longtap)
  4. 滑动
  5. 多点触控

1.单击

单击事件由touchstart、touchend组成,touchend后触发tap事件。

 

 
[html] view plain copy
 
  1. <view>  
  2.  <button type="primary"bindtouchstart="mytouchstart"bindtouchend="mytouchend"bindtap="mytap">点我吧</button>  
  3. </view>  
  4. mytouchstart: function(e){ console.log(e.timeStamp +'- touch start')  
  5. },mytouchend: function(e){ console.log(e.timeStamp +'- touch end')  
  6. },mytap: function(e){ console.log(e.timeStamp +'- tap')  
  7. }  

 

2.双击

双击事件由两个单击事件组成,两次间隔时间小于300ms认为是双击;微信官方文档没有双击事件,需要开发者自己定义处理。

 

[html] view plain copy
 
  1. <view>  
  2.  <buttontypebuttontype="primary"bindtap="mytap">点我吧</button>  
  3. </view>  

 


 

 3.长按

长按事件手指触摸后,超过350ms再离开。

 

[html] view plain copy
 
  1. <view>  
  2.  <button type="primary"bindtouchstart="mytouchstart"bindlongtap="mylongtap"  
  3.  bindtouchend="mytouchend"bindtap="mytap">点我吧</button>  
  4. </view>  
  5. mytouchstart: function(e){ console.log(e.timeStamp +'- touch start')  
  6. },//长按事件mylongtap: function(e){ console.log(e.timeStamp + '- long tap')  
  7.  },mytouchend:function(e){ console.log(e.timeStamp +'- touch end')  
  8. },mytap: function(e){ console.log(e.timeStamp +'- tap')  
  9. }  

 

单击、双击、长按属于点触事件,会触发touchstart、touchend、tap事件,touchcancel事件只能在真机模拟,不多说了。

事件 触发顺序
单击 touchstart → touchend → tap
双击 touchstart → touchend → tap → touchstart → touchend → tap
长按 touchstart → longtap → touchend → tap

 

4.滑动

手指触摸屏幕并移动,为了简化起见,下面以水平滑动和垂直滑动为例。 滑动事件由touchstart、touchmove、touchend组成

 

坐标图:

 

  1. 以屏幕左上角为原点建立直角坐标系。第四象限为手机屏幕,Y轴越往下坐标值越大(注意跟数学象限的区别)。
  2. 假设A点为touchstart事件触摸点,坐标为A(ax,ay),然后手指向上滑动到点B(bx,by),就满足条件by < ay;
  3. 同理,向右滑动到C(cx,cy),满足cx > ax;向下滑动到D(dx,dy),满足dy > ay;向左移动到E(ex,ey)满足ex < ax.
  4. 计算线段AB在Y轴上投影长度为m,在X轴上的投影长度为n
  5. 计算r = m/n,如果r > 1,视为向上滑动。
  6. 同理计算线段AC,AD,AE在Y轴投影长度与X轴的投影长度之比,得出向右向下向左的滑动。

以上没考虑r为1的情况。

[html] view plain copy
 
  1. <view>  
  2.  <buttontypebuttontype="primary"bindtouchstart="mytouchstart"bindtouchmove="mytouchmove">点我吧</button>  
  3. </view>  

 

 

[html] view plain copy
 
  1. mytouchstart: function (e) {  
  2.     var that = this;  
  3.     //开始触摸,获取触摸坐标  
  4.     console.log(e)  
  5.     that.setData({ startpoint: [e.touches[0].pageX, e.touches[0].pageY] });  
  6. },  
  7. //触摸点移动  
  8. mytouchmove: function (e) {  
  9.     //当前触摸点坐标  
  10.     var that = this;  
  11.     var curPoint = [e.touches[0].pageX, e.touches[0].pageY];  
  12.     var startpoint = that.data.startpoint;  
  13.     console.log(startpoint)  
  14.     console.log(curPoint)  
  15.     //比较pagex值  
  16.     if (curPoint[0] < startpoint[0]) {  
  17.         if (Math.abs(curPoint[0] - startpoint[0]) >= Math.abs(curPoint[1] - startpoint[1])) {  
  18.             console.log(e.timestamp + '-touch left move')  
  19.             that.setData({  
  20.                 dellStyle: "dellList"  
  21.             })  
  22.         } else {  
  23.             if (curPoint[1] >= startpoint[1]) {  
  24.                 console.log(e.timestamp + '-touch down move')  
  25.             } else {  
  26.                 console.log(e.timestamp + '-touch up move')  
  27.             }  
  28.         }  
  29.     } else {  
  30.         if (Math.abs(curPoint[0] - startpoint[0] >= Math.abs(curPoint[1] - startpoint[1]))) {  
  31.             console.log(e.timestamp + '-touch right move')  
  32.             that.setData({  
  33.                 dellStyle: "modList"  
  34.             })  
  35.         } else {  
  36.             if (curPoint[1] >= startpoint[1]) {  
  37.                 console.log(e.timestamp + '-touch down move')  
  38.             } else {  
  39.                 console.log(e.timestamp + '-touch up move')  
  40.             }  
  41.         }  
  42.     }  
  43. },  


 

 

5.多点触控

由于模拟器尚不支持多点触控,内测开放后,继续补充。

 

实际使用中遇到的坑;

本身使用的是 scroll-view 进行下拉刷新事件,想在页面list里面进行左滑动唤醒删除菜单,实际上写出来会冲突导致 scroll事件无法触发,默认滑动事件了。

长按:touchstart → longtap → touchend → tap

本身list绑定了单击事件点击进入详情页,准备增加一个长按唤醒操作菜单,实际体验并不好,长按之后手指不能直接离开屏幕那样会触发点击事件,需要轻微移动一下离开屏幕。

解决思路

前端绑定三个事件

 

[html] view plain copy
 
  1. bindtouchstart="mytouchstart" bindtouchend="mytouchend"  bindtap="bindtap"  


js处理通过点击开始结束判断点击屏幕时间,进行不同的业务触发

 

[html] view plain copy
 
  1. bindtap: function (e) {  
  2.     var that = this;  
  3.     //触摸时间距离页面打开的毫秒数    
  4.     var touchTime = that.data.touch_end - that.data.touch_start  
  5.     console.log(touchTime)  
  6.     //如果按下时间大于350为长按    
  7.     if (touchTime > 350) {  
  8.         wx.showModal({  
  9.             title: '提示',  
  10.             content: '这是一个模态弹窗',  
  11.             success: function (res) {  
  12.                 if (res.confirm) {  
  13.                     console.log('用户点击确定')  
  14.                 } else if (res.cancel) {  
  15.                     console.log('用户点击取消')  
  16.                 }  
  17.             }  
  18.         })  
  19.     } else {  
  20.         var id = e.currentTarget.dataset.id;  
  21.         wx.navigateTo({  
  22.             url: '../detail/detail?id=' + id  
  23.         })  
  24.     }  
  25. },  
  26. //按下事件开始    
  27. mytouchstart: function (e) {  
  28.     let that = this;  
  29.     that.setData({  
  30.         touch_start: e.timeStamp  
  31.     })  
  32.     console.log(e.timeStamp + '- touch-start')  
  33. },  
  34. //按下事件结束    
  35. mytouchend: function (e) {  
  36.     let that = this;  
  37.     that.setData({  
  38.         touch_end: e.timeStamp  
  39.     })  
  40.     console.log(e.timeStamp + '- touch-end')  
  41. },  
  42.  

 

大云网官方微信售电那点事儿

责任编辑:售电衡衡

免责声明:本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
我要收藏
个赞