移动端的touch事件
触摸事件的起源
随着智能手机和平板电脑的普及, 越来越多的人用移动设备浏览网页,我们平时在pc浏览器上用的鼠标事件,比如:click, mouseover等, 已经无法满足移动设备触摸屏的特点,触摸时代的到来,离不开那些触摸事件。
触摸事件touchstart、touchmove和touchend的出现是因为iOS版Safari浏览器为了向开发人员传达一些信息而新添加的事件。因为ios设备既没有鼠标也没有键盘,所以在为移动Safari浏览器开发交互性网页的时候,PC端的鼠标和键盘事件是不够用的。
在iPhone 3Gs发布的时候,其自带的移动Safari浏览器就提供了一些与触摸(touch)操作相关的新事件。随后,Android上的浏览器也实现了相同的事件。触摸事件(touch)会在用户手指放在屏幕上面的时候、在屏幕上滑动的时候或者是从屏幕上移开的时候出发。
事件类型
1.touchstart事件(触摸开始事件):当手指触摸屏幕时候触发,即使已经有一个手指放在屏幕上也会触发(触发一次)。
2.touchmove事件(触摸移动事件):当手指在屏幕上滑动的时候连续地触发。在这个事件发生期间,调用preventDefault()事件可以阻止滚动(当手指在屏幕上滑动,就会一直触发)。
3.touchend事件(触摸结束事件):当手指从屏幕上离开的时候触发。(触发一次)
4.touchcancel事件(触摸中断事件):当触摸中断时候触发。
注意:上面的这些事件都会冒泡,也都可以取消。
属性
虽然这些触摸事件没有在DOM规范中定义,但是它们却是以兼容DOM的方式实现的。所以,每个触摸事件的event对象都提供了在鼠标实践中常见的属性:
1.bubbles – 起泡事件的类型
2.cancelable – 是否用 preventDefault() 方法可以取消与事件关联的默认动作
3.clientX – 返回当事件被触发时,鼠标指针的水平坐标
4.clientY – 返回当事件触发时,鼠标指针的垂直坐标
5.screenX – 当某个事件被触发时,鼠标指针的水平坐标
6.screenY – 返回当某个事件被触发时,鼠标指针的垂直坐标
7.altKey – 该属性返回一个布尔值,表示在指定的事件发生时,Alt 键是否处于按下状态, event.altKey=true\false或者1\0
8.type – 触摸时触发的事件类型,比如touchstart
并且每个触摸事件都包括了三个触摸属性列表:
1 .touches:当前位于屏幕上的所有手指触摸点的一个列表。
2. targetTouches:当前元素对象上所有触摸点的列表。
3. changedTouches:涉及当前事件的触摸点的列表。
例:
<body>
<style>
#dom {
width:500px;
height:500px;
background:black;
}
</style>
<div id="dom"></div>
<script>
function onTouchStart(e){
console.log(e);
}
function start(){
var dom = document.getElementById('dom');
dom.addEventListener('touchstart', onTouchStart, false);
}
</script>
</body>
控制台输出如下:
触摸事件跟鼠标事件的触发先后顺序
touchstart > toucheend > mousemove > mousedown > mouseup > click
移动端触屏click点击事件延迟问题的解决方案
click事件在移动端和pc端均可以触发,但是在移动端有延迟现象。
1、背景
由于早期移动设备浏览网页时内容较小,为了增强用户体验,苹果公司专门为移动设备设计了双击放大的功能,以确保用户可以方便地放大网页内容,但是当用户单击按钮的时候,移动设备需要延迟约300ms执行,以判断用户是否是要双击。
2.解决方案
①给移动端加视口,禁止缩放(慎用。因为在移动端没有视口的情况下,用户是可以进行缩放的,默认会存在双击放大的功能,禁用后,那么双击放大的功能也就没有了)
例:
<meta name="viewport" content="width=device-width, user-scalable=no">
<!-- 关键词 user-scalable = no -->
②使用touch事件模拟一个点击事件
如下使用touchstart和touched封装了一个移动端的tap事件。
例:
var idcast = {
//传入dom元素
tap:function(dom,callback) {
//判断是否传入了dom元素,或者dom元素是否是一个对象
if(!dom||typeof dom != "object"){
return;
}
var startX,startY,time,moveX,moveY,distanceX,distanceY;
dom.addEventListener("touchstart",function(e) {
if(e.targetTouches.length>1) {
return;
}
startX = e.targetTouches[0].clientX;
startY = e.targetTouches[0].clientY;
time = Date.now();
});
dom.addEventListener("touchend",function(e) {
if(e.changedTouches.length>1) {//说明不止一个手指
return;
}
//判断时间差异
if(Date.now()-time>150){//长按操作
return;
}
//获取松开手指的时候的坐标与触摸开始时的坐标差异
moveX = e.changedTouches[0].clientX;
moveY = e.changedTouches[0].clientY;
distanceX = moveX - startX;
distanceY = moveY - startY;
//判断坐标差异
if(Math.abs(distanceX) < 6 && Math.abs(distanceY) <6) {//说明是点击而非滑动
//执行tap事件相应之后的处理操作
//若函数不为空才调用
callback&&callback(e);
console.log("移动端点击单击事件--tap事件");
}
})
}
}
③使用fastclick.js插件
fastclick.js是FT Labs专门为解决移动端浏览器 300 毫秒点击延迟问题所开发的一个轻量级的库。简而言之,FastClick 在检测到 touchend 事件的时候,会通过 DOM 自定义事件立即触发一个模拟 click 事件,并把浏览器在 300 毫秒之后真正触发的click事件阻止掉。 FastClick 的使用方法非常简单,在DOMContentLoaded事件之后,在body上调用FastClick.attach()即可。
例:
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
attach方法虽可在更具体的元素上调用,直接绑定到body上可以确保整个应用都能受益。当 FastClick 检测到当前页面使用meta设置了user-scalable=no或者 touch-action 属性的解决方案时,会静默退出。可以说,这是真正的跨平台方案出来之前一种很好的变通方案。