You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// 如果是pointerdown事件则firstTouch保存为e,否则是e.touches第一个firstTouch=_isPointerType ? e : e.touches[0]
这里只清楚e.touches[0]的处理逻辑,另一种不太明白,望有知晓的同学告知一下,感谢感谢。
复原终点坐标
// 一般情况下,在touchend或者cancel的时候,会将其清除,如果用户调阻止了默认事件,则有可能清空不了,但是为什么要将终点坐标清除呢?if(e.touches&&e.touches.length===1&&touch.x2){// Clear out touch movement data if we have it sticking around// This can occur if touchcancel doesn't fire due to preventDefault, etc.touch.x2=undefinedtouch.y2=undefined}
.on('touchend MSPointerUp pointerup',function(e){if((_isPointerType=isPointerEventType(e,'up'))&&!isPrimaryTouch(e))return// 取消长按事件 cancelLongTap()// 滑动事件,只要X轴或者Y轴的起始点和终点的距离超过30则认为是滑动,并触发滑动(swip)事件,// 紧接着马上触发对应方向的swip事件(swipLeft, swipRight, swipUp, swipDown)// swipeif((touch.x2&&Math.abs(touch.x1-touch.x2)>30)||(touch.y2&&Math.abs(touch.y1-touch.y2)>30))swipeTimeout=setTimeout(function(){if(touch.el){touch.el.trigger('swipe')touch.el.trigger('swipe'+(swipeDirection(touch.x1,touch.x2,touch.y1,touch.y2)))}touch={}},0)// touch对象的last属性,在touchstart事件中添加,所以触发了start事件便会存在 // normal tapelseif('last'intouch)// don't fire tap when delta position changed by more than 30 pixels,// for instance when moving to a point and back to origin// 只有当X轴和Y轴的变化量都小于30的时候,才认为有可能触发tap事件if(deltaX<30&&deltaY<30){// delay by one tick so we can cancel the 'tap' event if 'scroll' fires// ('tap' fires before 'scroll')tapTimeout=setTimeout(function(){// trigger universal 'tap' with the option to cancelTouch()// (cancelTouch cancels processing of single vs double taps for faster 'tap' response)// 创建自定义事件varevent=$.Event('tap')// 往自定义事件中添加cancelTouch回调函数,这样使用者可以通过该方法取消所有的事件event.cancelTouch=cancelAll// [by paper] fix -> "TypeError: 'undefined' is not an object (evaluating 'touch.el.trigger'), when double tap// 当目标元素存在,触发tap自定义事件if(touch.el)touch.el.trigger(event)// trigger double tap immediately// 如果是doubleTap事件,则触发之,并清除touchif(touch.isDoubleTap){if(touch.el)touch.el.trigger('doubleTap')touch={}}// trigger single tap after 250ms of inactivity// 否则在250毫秒之后。触发单击事件else{touchTimeout=setTimeout(function(){touchTimeout=nullif(touch.el)touch.el.trigger('singleTap')touch={}},250)}},0)}else{// 不是tap相关的事件touch={}}// 最后将变化量信息清空deltaX=deltaY=0})
if(deltaX<30&&deltaY<30){// delay by one tick so we can cancel the 'tap' event if 'scroll' fires// ('tap' fires before 'scroll')tapTimeout=setTimeout(function(){// trigger universal 'tap' with the option to cancelTouch()// (cancelTouch cancels processing of single vs double taps for faster 'tap' response)varevent=$.Event('tap')event.cancelTouch=cancelAll// [by paper] fix -> "TypeError: 'undefined' is not an object (evaluating 'touch.el.trigger'), when double tapif(touch.el)touch.el.trigger(event)}}
// trigger double tap immediatelyif(touch.isDoubleTap){if(touch.el)touch.el.trigger('doubleTap')touch={}}// trigger single tap after 250ms of inactivityelse{touchTimeout=setTimeout(function(){touchTimeout=nullif(touch.el)touch.el.trigger('singleTap')touch={}},250)}
前言
源码仓库
原文链接
事件简述
可以看到Zepto把这些方法都挂载到了原型上,这意味着,你可以直接用简写的方式例如
$('body').tap(callback)
前置条件
touch
: 用以存储手指操作的相关信息,例如手指按下时的位置,离开时的坐标等。touchTimeout
,tapTimeout
,swipeTimeout
,longTapTimeout
分别存储singleTap、tap、swipe、longTap事件的定时器。longTapDelay
:longTap事件定时器延时时间gesture
: 存储ieGesture事件对象我们根据下图以及对应的代码来理解滑动的时候方向是如何判定的。需要注意的是浏览器中的“坐标系”和数学中的坐标系还是不太一样,Y轴有点反过来的意思。
在触发长按事件之前先将
longTapTimeout
定时器取消,如果touch.last
还存在则触发之,为什么要判断touch.last
呢,因为swip
,doubleTap
,singleTap
会将touch对象置空,当这些事件发生的时候,自然不应该发生长按事件。方式都是类似,先调用clearTimeout取消定时器,然后释放对应的变量,等候垃圾回收。
整体结构分析
这里将详细代码暂时省略了,留出整体框架,可以看出Zepto在dom,ready的时候在
document
上添加了MSGestureEnd
,touchstart MSPointerDown pointerdown
,touchmove MSPointerMove pointermove
,touchcancel MSPointerCancel pointercancel
等事件,最后还给在window上加了scroll
事件。我们将目光聚焦在touchstart
,touchmove
,touchend
对应的逻辑,其他相对少见的事件在暂不讨论touchstart
要走到
touchstart
事件处理程序后续逻辑中,需要先满足一些条件。到底是哪些条件呢?先来看看isPointerEventType
,isPrimaryTouch
两个函数做了些什么。**
isPointerEventType
Pointer Event相关知识点击这里
isPrimaryTouch
根据mdn pointerType,其类型可以是
mouse
,pen
,touch
,这里只处理其值为touch并且isPrimary为true的情况。接着回到
其实就是过滤掉非触摸事件。
触摸点信息兼容处理
这里只清楚
e.touches[0]
的处理逻辑,另一种不太明白,望有知晓的同学告知一下,感谢感谢。复原终点坐标
存储触摸点部分信息
判断双击事件
处理长按事件
touchmove
手指移动的时候,做了三件事情。
touchend
touchend事件触发时,相应的注释都在上面了,但是我们来分解一下这段代码。
swip事件相关
手指离开后,通过判断x轴或者y轴的位移,只要其中一个跨度大于30便会触发
swip
及其对应方向的事件。tap,doubleTap,singleTap
这三个事件可能触发的前提条件是touch对象中还存在last属性,从touchstart事件处理程序中知道last在其中记录,而在touchend之前被清除的时机是长按事件被触发
longTap
,取消所有事件被调用cancelAll
只有当x轴和y轴的变化量都小于30的时候才会触发
tap
事件,注意在触发tap事件之前,Zepto还将往事件对象上添加了cancelTouch属性,对应的也就是cancelAll方法,即你可以通过他取消所有的touch相关事件。在发生触发tap事件之后,如果是doubleTap,则会紧接着触发doubleTap事件,否则250毫秒之后触发singleTap事件,并且都会讲touch对象置为空对象,以便下次使用
touchcancel
当
touchcancel
被触发的时候,取消所有的事件。scroll
当滚动事件被触发的时候,取消所有的事件(这里有些不解,滚动事件触发,完全有可能是要触发tap或者swip等事件啊)。
结尾
参考
移动端click延迟及zepto的穿透现象
新年第一发--深入不浅出zepto的Tap击穿问题
读Zepto源码之Touch模块
pointerType
[翻译]整合鼠标、触摸 和触控笔事件的Html5 Pointer Event Api
文章目录
touch.js
ie.js
data.js
form.js
zepto.js
event.js
ajax.js
The text was updated successfully, but these errors were encountered: