移动端点击事件
1.移动端点击事件click出现延迟
⼯作中接触了移动端,发现同事们都会⽤如下代码去写移动端的点击事件,尝试使⽤,屡试不爽,⼀旦没有⽤下边这段代码,点击事件就会
出现各种各样的问题,在连续使⽤了N多次之后(本⼈并没有爱钻研的精神~~有点⼉懒),终于决定⾃⼰上⽹查⼀些资料,看看到底是什么
原因呗。(解释jquery的⽅法data():在匹配元素上存储任意相关数据或返回匹配的元素集合中的第⼀个元素的给定名称的数据存储的值。
trigger():规定被选元素要触发的事件。)
//⾃定义tap
$(document).on("touchstart",function(e){
if(!$().hasClass("disable"))$().data("isMoved",0);
});
$(document).on("touchmove",function(e){
if(!$().hasClass("disable"))$().data("isMoved",1);
});
$(document).on("touchend",function(e){
if(!$().hasClass("disable")&&$().data("isMoved")==0)$().trigger("tap");
});
2.问题出在哪了
为什么要⽤tap事件代替click事件?答案:300毫秒延迟
这要追溯⾄2007年初。苹果公司在发布⾸款iPhone前⼣,遇到⼀个问题——当时的⽹站都是为⼤屏幕设备所设计的。于是苹果的⼯程师
们做了⼀些约定,应对iPhone这种⼩屏幕访问电脑版的⽹页的问题。这当中最出名的,当属双击缩放(doubletaptozoom)。
当⽤户⼀次点击屏幕之后,浏览器并不能⽴刻判断⽤户是要进⾏双击缩放,还是想要进⾏单击操作。因此,iOSSafari就等待300毫秒,以
判断⽤户是否再次点击了屏幕。
于是,300毫秒延迟就这么诞⽣了。
鉴于iPhone的成功,其他移动浏览器都复制了iPhoneSafari浏览器的多数约定,包括双击缩放,⼏乎现在所有的移动端浏览器都有这个功
能(嗯~尝试了⼀下好像微信浏览器没有再遵守这个双击缩放的约定)。之前⼈们刚刚接触移动端的页⾯,在欣喜的时候往往不会care这个
300ms的延时问题,可是如今移动端界⾯如⾬后春笋,⽤户对体验的要求也更⾼,这300ms带来的卡顿慢慢变得让⼈难以接受。
3.实例操作300ms出现的过程
⼀开始触摸事件touchstart、touchmove和touchend是iOS版Safari浏览器为了向开发⼈员传达⼀些信息新添加的事件。因为iOs设备既没有⿏
标也没有键盘,所以在为移动Safari浏览器开发交互性⽹页的时候,PC端的⿏标和键盘事件是不够⽤的。
在iPhone3Gs发布的时候,其⾃带的移动Safari浏览器就提供了⼀些与触摸(touch)操作相关的新事件。随后,Android上的浏览器也实现了
相同的事件(⼤家统⼀了,移动端浏览器都有了touch事件啦)。触摸事件(touch)会在⽤户⼿指放在屏幕上⾯的时候、在屏幕上滑动的时候
或者是从屏幕上移开的时候触发。下⾯具体说明:
touchstart事件:当⼿指触摸屏幕时候触发,即使已经有⼀个⼿指放在屏幕上也会触发。
touchmove事件:当⼿指在屏幕上滑动的时候连续地触发。这个事件发⽣期间,调⽤preventDefault()事件可以阻⽌滚动。
touchend事件:当⼿指从屏幕上离开的时候触发。
touchcancel事件:当系统停⽌跟踪触摸的时候触发。关于这个事件的确切时间,⽂档中并没有具体说明,这⾥不再详述。
touch事件及click事件同时绑定在⼀个元素上demo:(⼀⾔不合上代码~~指代事件类型)
$(document).on('touchstart','.wantUp',function(e){
$(".").append();
})
$(document).on('touchmove','.wantUp',function(e){
$(".").append();
})
$(document).on('touchend','.wantUp',function(e){
$(".").append();
})
$(document).on('click','.wantUp',function(e){
$(".").append();
});
可以看到,我在⼀个元素上边绑定了touchstart,touchmove,touchend,click事件,奇妙的事情发⽣了:
touch,click事件的执⾏顺序:touchstart>touchmove>touchend>click。很明显,touch事件执⾏完毕后才会到click事件,这就是我们所说
的300ms的延迟。
touchmove,click事件互斥,即touchmove触发执⾏,click事件不再执⾏,事件的执⾏顺序就为touchstart>touchmove(可以多次执⾏)>
touchend。
短暂触摸(点)⼀下屏幕,上述代码的事件的执⾏顺序:touchstart>touchend>click。
OK,到⽬前为⽌我们已经阐述了300ms的产⽣,⽽这300ms的产⽣还带来⼀个巨⼤的问题,点透事件。
4.点透事件
点透发⽣的条件:
A和B不是后代继承关系(如果是后代继承关系的话,就直接是冒泡之类的话题了(在此不再赘述))
A发⽣touch(也可以是click)后⽴即消失,B事件绑定click
Az-index⼤于B,即A显⽰在B浮层之上
点透发⽣的原因:
当⼿指触摸到屏幕的时候,系统⽣成两个事件,⼀个是touch⼀个是click,touch先执⾏,touch执⾏完成后,A从⽂档树上⾯消失了,⽽
且由于移动端click还有延迟200-300ms的关系,当系统要触发click的时候,发现在⽤户点击的位置上⾯,⽬前离⽤户最近的元素是B,所以
就直接把click事件作⽤在B元素上⾯了
ntListener('touch',function(e){
y='none';
});
k=function(){
('B莫名被点击了');
}
解决⽅案是touch阶段取消掉click事件:touch事件内调⽤:tDefault()
5.解决⽅案
以上问题的解决⽅案就是:既然浏览器统⼀了touch事件,就⽤touch事件去模拟click事件。
还记得⽂章最开始的那段代码吗?
//⾃定义tap
$(document).on("touchstart",function(e){
if(!$().hasClass("disable"))$().data("isMoved",0);
});
$(document).on("touchmove",function(e){
if(!$().hasClass("disable"))$().data("isMoved",1);
});
$(document).on("touchend",function(e){
if(!$().hasClass("disable")&&$().data("isMoved")==0)$().trigger("tap");
});
解释⼀下吧:现在原理就很明显了~
基于touchstart、touchmove、touchend这三个事件,通过事件委托的⽅式来实现tap事件。
是事件源的触发节点,$()是该节点的jQuery封装对象,isMoved这个就相当于⼀个开关,移动了置为1,没移动置为0。
第⼀步:监听touchstart事件,事件触发后通过jQuery的data⽅法设置该对象的isMoved状态为0。
第⼆步:监听touchmove事件,事件触发后通过jQuery的data⽅法设置该对象的isMoved状态为1。
第三步:监听touchend事件,事件触发后判断该对象是否touchMove过,没有则触发tap事件。
如何算tap事件:⼿指点上去不移动快速松开。
6.如何使⽤这段代码?
复制上述代码到页⾯js处
对该使⽤click事件的元素统⼀换成tap事件
端事件在移动端的兼容问题
1.1click事件的200~300ms延迟问题
由于移动端默认的布局视⼝宽度是980像素,所以⽹页⽂字⾮常⼩,为了快速让⽹页还原到原来的⼤⼩,Safari最新引⼊了双击缩放功能:
⽤户双击⼿机页⾯的时候,浏览器会智能的缩放当前页⾯到原始⼤⼩。
双击缩放的原理就是,当⽤户click⼀次之后,浏览器会经过约300ms之后检测是否再有⼀次click,如果有的话,就会缩放页⾯。
否则的话就是⼀个click事件。
由于双击缩放功能存在,click事件触发就会有⼤约200~300ms的延迟。
1.2dblclick事件失效
由于双击缩放的存在,pc端的dblclick事件也失效了。
2.移动端特有的touch事件
由于移动端设备⼤都具备触摸功能,所以移动端浏览器都引⼊了触摸(touch)事件。
touch相关的事件跟普通的其他dom事件⼀样使⽤,可以直接⽤addEventListener来监听和处理。
最基本的touch事件包括4个事件:
tart:当在屏幕上按下⼿指时触发
ove:当在屏幕上移动⼿指时触发
nd:当在屏幕上抬起⼿指时触发
ancel当⼀些更⾼级别的事件发⽣的时候(如电话接⼊或者弹出信息)会取消当前的touch操作,即触发touchcancel。⼀般会在
touchcancel时暂停游戏、存档等操作。
2.1touch事件与click事件同时触发
在很多情况下,触摸事件和⿏标事件会同时被触发(⽬的是让没有对触摸设备优化的代码仍然可以在触摸设备上正常⼯作)。
因为双击缩放检测的存在,在移动设备屏幕上点击操作的事件执⾏顺序:
touchstart(瞬间触发)→touchend→click(200-300ms延迟)
如果你使⽤了触摸事件,可以调⽤tDefault()来阻⽌⿏标事件被触发。
2.2touchstart事件
当⽤户⼿指触摸到的触摸屏的时候触发。事件对象的target就是touch发⽣位置的那个元素。
点击我!
varbox=elector("div");
ntListener("touchstart",function(e){
('touchstart');
});
2.3touchmove事件
当⽤户在触摸屏上移动触点(⼿指)的时候,触发这个事件。⼀定是先要触发touchstart事件,再有可能触发touchmove事件。
touchmove事件的target与最先触发的touchstart的target保持⼀致。touchmove事件和⿏标的moumove事件⼀样都会多次重复调⽤,所
以,事件处理时不能有太多耗时操作。不同的设备,移动同样的距离touchmove事件的触发频率是不同的。
注意:
1.即使⼿指移出了原来的target元素,则touchmove仍然会被⼀直触发,⽽且target仍然是原来的target元素。
ove事件会多次重复触发,由于移动端计算资源宝贵,尽量保证
vari=1;
varbox=elector("div");
varp=elector("p");
ntListener("touchmove",function(e){
TML=e+","+i++;
})
2.4touchend事件
当⽤户的⼿指抬起的时候,会触发touchend事件。如何⽤户的⼿指从触屏设备的边缘移出了触屏设备,也会触发touchend事件。
touchend事件的target也是与touchstart的target⼀致,即使已经移出了元素。
⼀次完整的touch事件的触发顺序和过程
2.5touchcancel事件
当触点由于某些原因被中断时触发。有⼏种可能的原因如下(具体的原因根据不同的设备和浏览器有所不同):
由于某个事件取消了触摸:例如触摸过程被⼀个模态的弹出框打断。
触点离开了⽂档窗⼝,⽽进⼊了浏览器的界⾯元素、插件或者其他外部内容区域。
当⽤户产⽣的触点个数超过了设备⽀持的个数,从⽽导致TouchList中最早的Touch对象被取消
touchcancel事件⼀般⽤于保存现场数据。⽐如:正在玩游戏,如果发⽣了。touchcancel事件,则应该把游戏当前状态相关的
⼀些数据保存起来。
3.触摸事件对象
TouchEvent是⼀类描述⼿指在触摸平⾯(触摸屏、触摸板等)的状态变化的事件。这类事件⽤于描述⼀个或多个触点,使开发者可以检测触
点的移动,触点的增加和减少,等等。
每个对象代表⼀个触点;每个触点都由其位置,⼤⼩,形状,压⼒⼤⼩,和⽬标描述。对象代表多个触点的⼀个列表.
3.1TouchEvent
的属性继承了和。
属性列表:
1.:⼀个对象,包含了代表所有从上⼀次触摸事件到此次事件过程中,状态发⽣了改变的触点的对象。
2.:⼀个对象,是包含了如下触点的对象:触摸起始于当前事件的⽬标上,并且仍然没有离开触摸平⾯的触点。
3.:⼀个对象,包含了所有当前接触触摸平⾯的触点的对象,⽆论它们的起始于哪个上,也⽆论它们状态是否发⽣了变化。
.box{
width:100px;
height:100px;
border:1pxsolid#09c;
background-color:#0dc;
}
=function(){
varbox=elector('.box');
ntListener('touchstart',function(e){
(e);//查看TouchEvent对象的属性和⽅法
});
}
3.2TouchList详解
⼀个TouchList代表⼀个触摸屏幕上所有触点的列表。
举例来讲,如果⼀个⽤户⽤三根⼿指接触屏幕(或者触控板),与之相关的TouchList对于每根⼿指都会⽣成⼀个Touch对象,共计3个.
1.只读属性:length
返回这个TouchList中Touch对的个数。(就是有⼏个⼿指接触到了屏幕)
2.⽅法:item(index)
返回TouchList中指定索引的Touch对象。
varbox=elector("div");
varp=elector("p");
ntListener("touchend",function(e){
TML=;//返回Touch对象的个数
for(vari=0;i<;i++){
//遍历出来每个Touch对象
((i));
}
})
测试多个⼿机触摸屏幕:
vardiv=elector("div");
varp=elector("p");
ntListener("touchstart",function(e){
varmsg=":"++
"
:"++
"
:"+;
TML=msg;
})
操作:
1.放1个⼿指在div上
2.先放1个⼿指在其他地⽅,然后再放1个⼿指在div上
3.先放1个⼿指在其他地⽅,然后再逐渐放2个⼿指在div上
3.3Touch详解
Touch表⽰⽤户和触摸设备之间接触时单独的交互点(asinglepointofcontact)。这个交互点通常是⼀个⼿指或者触摸笔,触摸设备通常是触摸
屏或者触摸板。
基本属性列表(都是只读):
编
号
属性名属性说明
fier表⽰每1个Touch对象的独⼀⽆⼆的identifier。有了这个identifier可以确保你总能追踪到这个Touch对象。
X触摸点相对于屏幕左边缘的x坐标。
Y触摸点相对于屏幕上边缘的y坐标。
X触摸点相对于浏览器的viewport左边缘的x坐标。不会包括左边的滚动距离。
Y触摸点相对于浏览器的viewport上边缘的y坐标。不会包括上边的滚动距离。
触摸点相对于document的左边缘的x坐标。与clientX不同的是,他包括左边滚动的距离,如果有的话。
触摸点相对于document的左边缘的y坐标。与clientY不同的是,他包括上边滚动的距离,如果有的话。
总是表⽰⼿指最开始放在触摸设备上的触发点所在位置的element。即使已经移出了元素甚⾄移出了document,他表⽰
的element仍然不变
案例:
varbox=elector("div");
varp=elector("p");
hstart=function(e){
vartouchList=dTouches;
for(vari=0;i<;i++){
vartouch=touchList[i];
varmsg=`id:${fier}
screenX:${X}
screenY:${Y}
clientX:${X}
clientY:${Y}
pageX:${}
pageY:${}
target:${me}
`;
TML=msg;
}
}
没有左右滚动:
左右滚动:pageX明显⼤于clientX
4.封装移动端tap事件
由于点击事件经常使⽤,如果⽤click会有延迟问题,⼀般我们会⽤touch事件模拟移动端的点击事件,以下是封装的⼏个事件,仅供参考。
(function(window){//传⼊window,提⾼变量的查找效率
functionmyQuery(lector){//这个函数就是对外提供的接⼝。
//调⽤这个函数的原型对象上的_init⽅法,并返回
ype._init(lector);
}
ype={
/*初始化⽅法,获取当前query对象的⽅法*/
_init:function(lector){
if(typeoflector=="string"){
//把查找到的元素存⼊到这个原型对象上。
=elector(lector);
//返回值其实就是原型对象。
returnthis;
}
},
/*单击事件:
*为了规避click的300ms的延迟,⾃定义⼀个单击事件
*触发时间:
*当抬起⼿指的时候触发
*需要判断⼿指落下和⼿指抬起的事件间隔,如果⼩于500ms表⽰单击时间。
*如果是⼤于等于500ms,算是长按时间
**/
tap:function(handler){
ntListener("touchstart",touchFn);
ntListener("touchend",touchFn);
varstartTime,
endTime;
functiontouchFn(e){
tDefault()
switch(){
ca"touchstart":
startTime=newDate().getTime();
break;
ca"touchend":
endTime=newDate().getTime();
if(endTime-startTime<500){
(this,e);
}
break;
}
}
},
/**
*长按
*@paramhandler
*/
longTag:function(handler){
ntListener("touchstart",touchFn);
ntListener("touchmove",touchFn);
ntListener("touchend",touchFn);
vartimerId;
functiontouchFn(e){
switch(){
ca"touchstart"://500ms之后执⾏
timerId=tTimeout(function(){
(this,e);
},500)
break;
ca"touchmove":
//如果中间有移动也清除定时器
clearTimeout(timerId)
break;
ca"touchend":
//如果在500ms之内抬起了⼿指,则需要定时器
clearTimeout(timerId);
break;
}
}
},
/**
*左侧滑动。
*记录⼿指按下的左边,在离开的时候计算deltaX是否满⾜左滑的条件
*/
slideLeft:function(handler){
ntListener("touchstart",touchFn);
ntListener("touchend",touchFn);
varstartX,startY,endX,endY;
functiontouchFn(e){
tDefault();
varfirstTouch=dTouches[0];
switch(){
ca"touchstart":
startX=;
startY=;
break;
ca"touchend":
endX=;
endY=;
//x⽅向移动⼤于y⽅向的移动,并且x⽅向的移动⼤于25个像素,表⽰在向左侧滑动
if((endX-startX)>=(endY-startY)&&startX-endX>=25){
(this,e);
}
break;
}
}
},
/*右侧滑动*/
rightLeft:function(e){
//TODO:
}
}
window.$=y=myQuery;
})(window);
//========================
//使⽤:
$("div").tap(function(e){
("单击事件")
})
$("div").longTag(function(){
("长按事件");
})
$("div").slideLeft(function(e){
(this);
TML="左侧滑动了....."
})
5.触摸⼿势封装相关的框架及事件
⼿势相关的事件⼀般就是tap类(触屏)和滑动(swipe)事件两类。都是基于原⽣的touchstart、touchmove、touchend事件,封装成不同的
⼿势类型⾃定义事件。
5.1tap类事件
触碰事件,我⽬前还不知道它和touch的区别,⼀般⽤于代替click事件,有taplongTapsingleTapdoubleTap四种之分。
:⼿指碰⼀下屏幕会触发
p:⼿指长按屏幕会触发
Tap:⼿指碰⼀下屏幕会触发
Tap:⼿指双击屏幕会触发
5.2swipe类事件
滑动事件,有swipeswipeLeftswipeRightswipeUpswipeDown五种之分。
:⼿指在屏幕上滑动时会触发
eft:⼿指在屏幕上向左滑动时会触发
ight:⼿指在屏幕上向右滑动时会触发
p:⼿指在屏幕上向上滑动时会触发
own:⼿指在屏幕上向下滑动时会触发
5.3zepto的⼿势相关事件
是⼀个轻量级的针对现代⾼级浏览器的JavaScript库,它适配了jQuery的⼤部分api,也就是jQuery怎么⽤,就怎么⽤。它⾮常⼩,
⾮常适合移动端。
的touch模块中封装了⼿势相关的代码。封装了再触摸设备上触发tap–和swipe–相关事件,也适⽤于所有的touch(iOS,Android)
和pointer事件(WindowsPhone)。
触屏事件:tap、singleTap、doubleTap、longTap(>750ms)
滑动事件:swipe、swipeLeft,、swipeRight,、swipeUp,、swipeDown
$('#itemsli').swipe(function(){
$('.delete').hide()
$('.delete',this).show()
})
$('.delete').tap(function(){
$(this).parent('li').remove()
})
5.4其他移动端⼿势相关库
1.
2.
hammer提供了不仅仅tap、swipe等事件,还提供了:pan(平移)、pinch类(捏拿缩放)、press类(按住)、rotate类(旋转)类⼿
势⽀持,
6.移动端点击穿透问题
如果某个返回按钮的位置,恰好在要返回的这个页⾯的带有href属性的a标签的范围内,在点击返回按钮后,页⾯快速切换到有a标签的页
⾯,300ms后触发了click事件,从⽽触发了a标签的意外跳转,这个就是典型的点击穿透问题。罪魁祸⾸其实就是a标签跳转默认是click事件
触发,⽽移动端的touch事件触发之后,依然会在300ms后触发click事件。
解决办法:
1.就是阻⽌触发touch事件完成后的click事件。
2.不要混⽤touch和click事件。显然不可能都绑定click事件,因为要解决300ms延迟问题(除了fastclick),那么只能都绑定touch事件,这样
click事件永远不会被触发。
注意:zepto并没有阻⽌click事件,所以使⽤zepto的tap事件依然会导致点击穿透问题,你需要⼿动添加tDefault()来阻
⽌click事件。
本文发布于:2022-12-29 22:33:42,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/55811.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |