移动web开发之touch事件

时间:2022-09-08 18:17:41

前面的话

  iOS版Safari为了向开发人员传达一些特殊信息,新增了一些专有事件。因为iOS设备既没有鼠标也没有键盘,所以在为移动Safari开发交互性网页时,常规的鼠标和键盘事件根本不够用。随着Android 中的WebKit的加入,很多这样的专有事件变成了事实标准,导致W3C开始制定Touch Events规范。本文将详细介绍移动端touch事件

概述

  包含iOS 2.0软件的iPhone 3G发布时,也包含了一个新版本的Safari浏览器。这款新的移动Safari提供了一些与触摸(touch)操作相关的新事件。后来,Android上的浏览器也实现了相同的事件。触摸事件会在用户手指放在屏幕上面时、在屏幕上滑动时或从屏幕上移开时触发。具体来说,有以下几个触摸事件

touchstart:当手指触摸屏幕时触发;即使已经有一个手指放在了屏幕上也会触发
touchmove:当手指在屏幕上滑动时连续地触发。在这个事件发生期间,调用preventDefault()可以阻止滚动
touchend:当手指从屏幕上移开时触发
touchcancel:当系统停止跟踪触摸时触发(不常用)。关于此事件的确切触发时间,文档中没有明确说明

【touchenter 和 touchleave】

  触摸事件规范中曾经包含touchenter和touchleave事件,这两个事件在用户手指移入或移出某个元素时触发。但是这两个事件从来没有被实现。微软有这两个事件的替代事件,但是只有IE浏览器支持。某些情况下可以知道用户手指滑入滑出某个元素是素是非常有用的,所以希望这两个事件可以重返规范

  在触摸事件中,常用的是touchstart、touchumove和touchend这三个事件,与鼠标事件的对应如下

鼠标         触摸
mousedown touchstart
mousemove touchmove
mouseup touchend

  [注意]touch事件在chrome模拟器下部分版本使用DOM0级事件处理程序的方式来添加事件无效

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#test{height:200px;width:200px;background:lightblue;}
</style>
</head>
<body>
<div id="test"></div>
<script>
(function(){
var
stateMap = {
touchstart_index : ,
touchmove_index : ,
touchend_index :
},
elesMap = {
touch_obj: document.getElementById('test')
},
showIndex, handleTouch; showIndex = function ( type ) {
elesMap.touch_obj.innerHTML = type + ':' + (++stateMap[type + '_index']);
}; handleTouch = function ( event ) {
showIndex( event.type );
}; elesMap.touch_obj.addEventListener('touchstart', function(event){handleTouch(event);});
elesMap.touch_obj.addEventListener('touchmove', function(event){handleTouch(event);});
elesMap.touch_obj.addEventListener('touchend', function(event){handleTouch(event);});
})(); </script>
</body>
</html>

300ms

  300ms问题是指在某个元素执行它的功能和执行touch事件之间有一个300毫秒的间隔。鼠标事件、焦点事件、浏览器默认行为等相较于touch事件,都存在着300ms的延迟

【点透】

  因为300ms的存在,会造成常见的点透问题。先来看例子

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#test {position: absolute;top: ;left: ;opacity: 0.5;height: 200px;width: 200px;background: lightblue;}
</style>
</head>
<body>
<a href="https://baidu.com">百度</a>
<div id="test"></div>
<script>
(function () {
var
elesMap = {
touchObj: document.getElementById('test')
},
fnHide, onTouch;
fnHide = function (type) {
elesMap.touchObj.style.display = 'none';
};
onTouch = function (event) {
fnHide();
};
elesMap.touchObj.addEventListener('touchstart', function(event){onTouch(event);});
})();
</script>
</body>
</html>

  浅蓝色的半透明div被点击(触发touch事件)后,如果点击位置正好位于链接的上方,则会触发链接跳转的默认行为。详细解释是,点击页面后,浏览器会记录所点击的页面坐标,300ms后,在该坐标找到元素。在该元素上触发点击行为。因此,如果300ms内同一页面坐标的上层元素消失后,300ms后在下层元素上触发点击行为。这就造成了点透问题

  造成这个问题,是因为触摸屏幕的行为被重载(overload)了。在手指触摸屏幕的瞬间,浏览器无法预知用户是在轻触(Tap)、双触(Double-Tap)、滑动(Swipe)、按住不放(Hold)还是其他什么操作。唯一保险的做法就是等上一会儿看接下来会发生什么

  问题是在于双触(Double-Tap)。即便是浏览器检测出手指离开了屏幕,它仍然无法判断接下来做什么。因为浏览器无法知道手指是会再次回到屏幕,还是就此结束触发轻触事件以及事件级联。为了确定这一点,浏览器不得不等待一小段时间。浏览器开发者找到一个最佳时间间隔,就是300毫秒

【解决办法】

  1、在touch事件的事件处理程序中增加300ms的延迟

    (function () {
var
elesMap = {
touchObj: document.getElementById('test')
},
fnHide, onTouch;
fnHide = function (type) {
elesMap.touchObj.style.display = 'none';
};
onTouch = function (event) {
setTimeout(function(){
fnHide();
},30);
};
elesMap.touchObj.addEventListener('touchstart', function (event) { onTouch(event); });
})();

  2、使用缓动动画,增加300ms的过渡效果,注意display属性无法使用transition

  3、加入中间层的dom元素,让中间层接受这个穿透事件,稍后隐藏

  4、上下两级都使用tap事件,但默认行为不可避免

  5、在document上的touchstart事件,阻止默认行为。

document.addEventListener('touchstart',function(e){
e.preventDefault();
})

  接着,添加a标签的跳转行为

a.addEventListener('touchstart',function(){
window.location.href = 'https://cnblogs.com';
})

  但是,这种方法有副作用,会造成页面无法滚动、文本无法选中等。如果在某个元素上,需要恢复文本选中的行为,则可以使用阻止冒泡来恢复

el.addEventListener('touchstart',function(e){
e.stopPropagation();
})

  

事件对象

【基础信息】

  每个触摸事件的event对象都提供了在鼠标事件中常见的属性,包括事件类型、事件目标对象、事件冒泡、事件流、默认行为等

  以touchstart为例,示例代码如下

  <script>
(function () {
var
elesMap = {
touchObj: document.getElementById('test')
},
onTouch;
onTouch = function (e) {
console.log(e)
};
elesMap.touchObj.addEventListener('touchstart', function (event) { onTouch(event); });
})();
</script>

  1、currentTarget属性返回事件正在执行的监听函数所绑定的节点

  2、target属性返回事件的实际目标节点

  3、srcElement属性与target属性功能一致

//当前目标
currentTarget:[object HTMLDivElement]
//实际目标
target:[object HTMLDivElement]
//实际目标
srcElement:[object HTMLDivElement]

  4、eventPhase属性返回一个整数值,表示事件目前所处的事件流阶段。0表示事件没有发生,1表示捕获阶段,2表示目标阶段,3表示冒泡阶段

  5、bubbles属性返回一个布尔值,表示当前事件是否会冒泡。该属性为只读属性

  6、cancelable属性返回一个布尔值,表示事件是否可以取消。该属性为只读属性

//事件流
eventPhase:
//可冒泡
bubbles: true
//默认事件可取消
cancelable: true

【touchList】

  除了常见的DOM属性外,触摸事件对象有一个touchList数组属性,其中包含了每个触摸点的信息。如果用户使用四个手指触摸屏幕,这个数组就会有四个元素。一共有三个这样的数组

  1、touches:当前触摸屏幕的触摸点数组(至少有一个触摸在事件目标元素上)

  2、changedTouches :导致触摸事件被触发的触摸点数组

  3、targetTouches:事件目标元素上的触摸点数组

  如果用户最后一个手指离开屏幕触发touchend事件,这最后一个触摸点信息不会出现在targetTouches和touches数组中,但是会出现在changedTouched数组中。因为是它的离开触发了touchend事件,所以changedTouches数组中仍然包含它。上面三个数组中,最常用的是changedTouches数组

    (function () {
var
elesMap = {
touchObj: document.getElementById('test')
},
onTouch;
onTouch = function (e) {
elesMap.touchObj.innerHTML = 'touches:' + e.touches.length
+ '<br>changedTouches:' + e.changedTouches.length
+ '<br>targetTouches:' + e.targetTouches.length;
};
elesMap.touchObj.addEventListener('touchstart', function (event) { onTouch(event); });
})();

【事件坐标】

  上面这些触摸点数组中的元素可以像普通数组那样用数字索引。数组中的元素包含了触摸点的有用信息,尤其是坐标信息。每个Touch对象包含下列属性

clientx:触摸目标在视口中的x坐标
clientY:触摸目标在视口中的y坐标
identifier:标识触摸的唯一ID
pageX:触摸目标在页面中的x坐标(包含滚动)
pageY:触摸目标在页面中的y坐标(包含滚动)
screenX:触摸目标在屏幕中的x坐标
screenY:触摸目标在屏幕中的y坐标
target:触摸的DOM节点目标

  changedTouches数组中的第一个元素就是导致事件触发的那个触摸点对象(通常这个触摸点数组不包含其他对象)。这个触摸点对象含有clientX/Y和pageX/Y坐标信息。除此之外还有screenX/Y和x/y,这些坐标在浏览器间不太一致,不建议使用

  clientX/Y和pageX/Y的区别在于前者相对于视觉视口的左上角,后者相对于布局视口的左上角。布局视口是可以滚动的

    (function () {
var
elesMap = {
touchObj: document.getElementById('test')
},
onTouch;
onTouch = function (e) {
var touch = e.changedTouches[];
elesMap.touchObj.innerHTML = 'clientX:' + touch.clientX + '<br>clientY:' + touch.clientY
+ '<br>pageX:' + touch.pageX + '<br>pageY:' + touch.pageY
+ '<br>screenX:' + touch.screenX + '<br>screenY:' + touch.screenY
};
elesMap.touchObj.addEventListener('touchstart', function (event) { onTouch(event); });
})();

移动web开发之touch事件的更多相关文章

  1. Android开发之Touch事件分发机制

    原地址http://www.cnblogs.com/linjzong/p/4191891.html Touch事件分发中只有两个主角:ViewGroup和View.Activity的Touch事件事实 ...

  2. Vim下的Web开发之html&comma;CSS&comma;javascript插件

    Vim下的Web开发之html,CSS,javascript插件   HTML 下载HTML.zip 解压HTML.zip,然后将里面的所有文件copy到C:\Program Files\Vim\vi ...

  3. Web开发之Tomcat&amp&semi;Servlet

    <!doctype html>01 - JavaEE - Tomcat&Servlet figure:first-child { margin-top: -20px; } #wri ...

  4. 移动web开发之rem适配布局

    移动web开发之rem适配布局 方案: 页面布局文字能否随着屏幕大小变化而变化 流式布局和flex布局主要针对于宽度布局,那高度如何布局? 怎样让屏幕发生变化的时候元素高度和宽度等比例缩放? 1. r ...

  5. 移动端Web界面滚动touch事件

    解决办法一: elem.addEventListener( 'touchstart', fn, { passive: false } ); 解决办法二: * { touch-action: pan-y ...

  6. &period;NET Web开发之&period;NET MVC框架

    摘要:MVC是一种架构设计模式,该模式主要应用于图形化用户界面(GUI)应用程序.那么什么是MVC?MVC由三部分组成:Model(模型).View(视图)及Controller(控制器). MVC概 ...

  7. HTML5&plus;JS手机web开发之jQuery Mobile初涉

    一.起始之语 我一直都是在PC上折腾网页的,这会儿怎么风向周边捣鼓起手机网页开发呢?原因是公司原先使用Java开发的产品,耗了不少人力财力,但是最后的效果却不怎么好.因为,Android系统一套东西, ...

  8. web 开发之js---js 多线程编程

    AJAX 开发中的难题 试试多线程编程 想了解更多 有关作者   转载注明出处:http://www.infoq.com/cn/articles/js_multithread 虽然有越来越多的网站在应 ...

  9. vert&period;x学习(三),Web开发之Thymeleaf模板的使用

    在vert.x中使用Thymeleaf模板,需要引入vertx-web-templ-thymeleaf依赖.pom.xml文件如下 <?xml version="1.0" e ...

随机推荐

  1. Jquery 下实现 图片大图预览效果

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  2. Android之 -WebView实现离线缓存阅读

    前言 本篇博客要实现的是一个离线下载和离线阅读的功能,这是很多阅读类app都常见的一个功能,典型的应用就是网易新闻.什么是离线下载?其实这个概念是比较模糊,是离线之后下载呢,还是下载之后离线,但稍微有 ...

  3. 安卓向服务器发送List数据

    第一步: 首先写一个自定义的JavaBean,以UserInfo.java为例,需要实现对象序列化的接口,因为之后输出流对象需要实现输出可序列化的对象.不这样的话,后续时发送时会报异常 package ...

  4. ZOJ 3511 不相交切切多边形 线段树求最大边数

    题意: n多凸边形 m刀 (把n切m刀,问切完后的图形中 最多的边数 是多少) 切a点-b点 数据保证切的刀不会相交 思路: 2点之间的剩余点数就是边数, 把a-b距离 近 排序 切完一刀就统计一下切 ...

  5. 每日一小练——Eratosthenes 筛选法

    上得厅堂.下得厨房,写得代码.翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:Eratosthenes筛选法 内容: 求质数是一个非常普遍的问题,通常不外乎用数去除.除到不尽时,给定的数就是质数.可是 ...

  6. 各类数据库url

    msql: jdbc:mysql://127.0.0.1:3306/databaseName ms-sql jdbc:microsoft:sqlserver://127.0.0.1:1433;Data ...

  7. Java中获取当前日期

    java.util.Date date = new Date();java.Text.SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd ...

  8. phpcmsV9于基本介绍

    1.phpcms做企业站 2.内容+管理栏目=页面显示的导航 3.文件目录结构 根目录 api 接口文件目录 caches 缓存文件目录 confings 系统配置文件目录 caches_*系统缓存目 ...

  9. jquery 第一章

    1.本章目标    了解jquery    了解jquery和js的区别    掌握jquery的入门    掌握jquery对象和dom对象的区别2.jquery简介    jquery是一个轻量级 ...

  10. jq源码判断数据类型

    4.Object.prototype.toString.call() 1 var a = Object.prototype.toString; 2 3 console.log(a.call(&quot ...