一、click 和 tap 比较

两者都会在点击时触发,但是在手机WEB端,click会有 200~300 ms,所以请用tap代替click作为点击事件。

singleTap和doubleTap 分别代表单次点击和双次点击。

二、关于tap的点透处理

在使用zepto框架的tap来移动设备浏览器内的点击事件,来规避click事件的延迟响应时,有可能出现点透的情况,即点击会触发非当前层的点击事件。

处理方式:

(1)、

github上有一个叫做fastclick的库,它也能规避移动设备上click事件的延迟响应,https://github.com/ftlabs/fastclick
将它用script标签引入页面(该库支持AMD,于是你也可以按照AMD规范,用诸如require.js的模块加载器引入),并且在dom ready时初始化在body上,如:

1
2
3
$(function(){
    new

FastClick(document.body);
})

然后给需要“无延迟点击”的元素绑定click事件(注意不再是绑定zepto的tap事件)即可。
当然,你也可以不在body上初始化它,而在某个dom上初始化,这样,只有这个dom和它的子元素才能享受“无延迟”的点击

实践开发中发现,当元素绑定fastclick后,click响应速度比tap还要快一点点。哈哈

(2)、为元素绑定touchend事件,并在内部加上e.preventDefault();

$demo.on('touchend',function(e){
//
改变了事件名称,tap是在body上才被触发,而touchend是原生的事件,在dom本身上就会被捕获触发
    $demo.hide()
    e.preventDefault();
//
阻止“默认行为”
})

三、touch事件touch是针对触屏手机上的触摸事件。现今大多数触屏手机webkit内核提供了touch事件的监听,让开发者可以获取用户触摸屏幕时的一些信息。

其中包括:touchstart,touchmove,touchend,touchcancel 这四个事件

touchstart,touchmove,touchend事件可以类比于mousedown,mouseover
,mouseup的触发。

touchstart
: 当手指触摸到屏幕会触发;

touchmove
: 当手指在屏幕上移动时,会触发;

touchend
: 当手指离开屏幕时,会触发;

而touchcancel许多人不知道它在什么时候会被触发而忽略它,其实当你的手指还没有离开屏幕时,有系统级的操作发生时就会触发touchcancel,例如alert和confirm弹框,又或者是android系统的功能弹窗。

例如:

这4个事件的触发顺序为:

touchmove -> …… -> touchmove ->touchend

但是单凭监听上面的单个事件,不足以满足我们去完成监听在触屏手机常见的一些手势操作,如双击、长按、左右滑动、缩放等手势操作。需要组合监听这些事件去封装对这类手势动作。

其实市面上很多框架都针对手机浏览器封装了这些手势,例如jqmobile、zepto、jqtouch,不过悲剧发生了,对于某些android系统(我自己测试到的在android 4.0.x),touchmove和touchend事件不能被很好的触发,举例子说明下:

比如手指在屏幕由上向下拖动页面时,理论上是会触发 一个 touchmove ,和最终的 touchend ,可是在android 4.0上,touchmove只被触发一次,触发时间和touchstart 差不多,而touchend直接没有被触发。这是一个非常严重的bug,在google Issue已有不少人提出  http://code.google.com/p/android/issues/detail?id=19827

暂时我只发现在android 4.0会有这个bug,据说 ios 3.x的版本也会有。

而显然jqmobile、zepto等都没有意识到这个bug对监听实现带来的严重影响,所以在直接使用这些框架的event时,或多或少会出现兼容性问题!(个人亲身惨痛经历)

所以我修改了一下zepto的event模块,并且添加了一些事件触发参数,加强了一下可用性。

(function($){

$.fn.touchEventBind = function(touch_options)

{

var touchSettings = $.extend({

tapDurationThreshold : 250,//触屏大于这个时间不当作tap

scrollSupressionThreshold : 10,//触发touchmove的敏感度

swipeDurationThreshold : 750,//大于这个时间不当作swipe

horizontalDistanceThreshold: 30,//swipe的触发垂直方向move必须小于这个距离

verticalDistanceThreshold: 75,//swipe的触发水平方向move必须大于这个距离

tapHoldDurationThreshold: 750,//swipe的触发水平方向move必须大于这个距离

doubleTapInterval: 250//swipe的触发水平方向move必须大于这个距离

}, touch_options || {})

var touch = {}, touchTimeout ,delta ,longTapTimeout;

function parentIfText(node){

return 'tagName' in node ? node : node.parentNode

}

function swipeDirection(x1, x2, y1, y2){

var xDelta = Math.abs(x1 - x2), yDelta = Math.abs(y1 - y2)

return xDelta >= yDelta ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')

}

function longTap()

{

longTapTimeout = null

touch.el.trigger('longTap');

touch.longTap = true;

touch = {};

}

function cancelLongTap()

{

if (longTapTimeout) clearTimeout(longTapTimeout)

longTapTimeout = null

}

this.data('touch_event_bind',"true");

this.bind('touchstart', function(e)

{

touchTimeout && clearTimeout(touchTimeout);

touch.el = $(parentIfText(e.touches[0].target));

now = Date.now();

delta = now - (touch.last_touch_time || now);

touch.x1 = e.touches[0].pageX;

touch.y1 = e.touches[0].pageY;

touch.touch_start_time = now;

touch.last_touch_time = now;

if (delta > 0 && delta <= touchSettings.doubleTapInterval) touch.isDoubleTap = true;

longTapTimeout = setTimeout(function(){

longTap();

},touchSettings.tapHoldDurationThreshold);

}).bind('touchmove',function(e)

{

cancelLongTap();

touch.x2 = e.touches[0].pageX;

touch.y2 = e.touches[0].pageY;

// prevent scrolling

if ( Math.abs( touch.x1 - touch.x2 ) > touchSettings.scrollSupressionThreshold )

{

e.preventDefault();

}

touch.touch_have_moved = true;

}).bind('touchend',function(e)

{

cancelLongTap();

now = Date.now();

touch_duration = now - (touch.touch_start_time || now);

if(touch.isDoubleTap)

{

touch.el.trigger('doubleTap');

touch = {};

}

else if(!touch.touch_have_moved && touch_duration < touchSettings.tapDurationThreshold)

{

touch.el.trigger('tap');

touchTimeout = setTimeout(function(){

touchTimeout = null;

touch.el.trigger('singleTap');

touch = {};

}, touchSettings.doubleTapInterval);

}

else if ( touch.x1 && touch.x2 )

{

if ( touch_duration < touchSettings.swipeDurationThreshold && Math.abs( touch.x1 - touch.x2 ) > touchSettings.verticalDistanceThreshold && Math.abs( touch.y1 - touch.y2 ) < touchSettings.horizontalDistanceThreshold )

{

touch.el.trigger('swipe').trigger( touch.x1 > touch.x2 ? "swipeLeft" : "swipeRight" );

touch = {};

}

}

}).bind('touchcancel',function(e){

touchTimeout && clearTimeout(touchTimeout);

cancelLongTap();

touch = {};

})

}

$.fn.touchbind = function(m,callback,touch_options)

{

if(this.data('touch_event_bind')!="true")

{

this.touchEventBind(touch_options);

}

this.bind(m,callback);

}

;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m)

{

$.fn[m] = function(touch_options,callback)

{

if(typeof(touch_options)=="object" && typeof(callback)=="function")

{

return this.touchbind(m, callback , touch_options)

}

else if(typeof(touch_options)=="function")

{

var callback = touch_options;

return this.touchbind(m, callback)

}

}

})

})(Zepto)

上面的代码基于zepto,替换掉原先zepto的这块就OK了,不过独立写开来也是可以的,我只是用到了zepto的 bind函数来做事件监听而已,实现的思路其实也很清晰。

兼容的解决办法是在 touchmove 时判断手势趋势大于预设值时(大于预设值证明有 move的动作趋势),停止默认的操作e.preventDefault(),这样touchedn就可以被正常触发了。真心认为google的这个bug是一个极其影响手机web交互的bug!

web开发,click,touch,tap事件浅析的更多相关文章

  1. 移动端WEB开发,click,touch,tap事件浅析

    一.click 和 tap 比较 两者都会在点击时触发,但是在手机WEB端,click会有 200~300 ms,所以请用tap代替click作为点击事件. singleTap和doubleTap 分 ...

  2. 移动端web开发,click touch tap区别

    转自: http://blog.csdn.net/sly94/article/details/51701188 移动端用tap时会有穿透问题 一:click与tap比较 click与tap都会触发点击 ...

  3. zepto+mui开发中的tap事件重复执行

    zepto.js和mui一起使用的时候,因为都有tap事件绑定tab事件后会多次触发还会报错,这时不引用zepto中的touch.js就可以了,只用mui的tap相关事件. $(function () ...

  4. iOS开发中didSelectRowAtIndexPath tap事件响应延迟

    为UITableViewCell添加tapped事件,代码如下: class VideoViewController: UIViewController , UITableViewDataSource ...

  5. 移动端click时间、touch事件、tap事件

    一.click 和 tap 比较 两者都会在点击时触发,但是在手机WEB端,click会有 200~300 ms,所以请用tap代替click作为点击事件. singleTap和doubleTap 分 ...

  6. 移动端click时间、touch事件、tap事件详解

    一.click 和 tap 比较 两者都会在点击时触发,但是在手机WEB端,click会有 200~300 ms,所以请用tap代替click作为点击事件. singleTap和doubleTap 分 ...

  7. Touch事件在移动端web开发中的详解

    一.pc端事件回顾 HTML事件.DOM0事件.DOM2事件 事件对象. 如果上述概念不清楚,请先去了解. 二.移动端事件简介 2.1 pc端事件在移动端的问题 ​ 移动设备主要特点是不配备鼠标,键盘 ...

  8. javascript移动设备Web开发中对touch事件的封装实例

    在触屏设备上,一些比较基础的手势都需要通过对 touch 事件进行二次封装才能实现.zepto 是移动端上使用率比较高的一个类库,但是其 touch 模块模拟出来的一些事件存在一些兼容性问题,如 ta ...

  9. 彻底理解和解决移动WEB开发中CLICK点透问题

    在移动WEB开发中,有时候可能会出现点透问题,本文将围绕这个TAP点透问题,详细的讲述到底什么是点透,为什么会出现点透,如何避免出现点透,如果不可避免的出现了,如何解决解决移动WEB开发中CLICK点 ...

随机推荐

  1. oracle RAC的客户端HA配置

    在ORACLE 9i RAC 环境下,为了做到高可用性,需要对客户端的tnsnames.ora这个文件进行配置,在oracle中这样的配置叫做TAF,这个配置不能使用NETCA配置程序生成.其中ORA ...

  2. 关联规则&Apriori算法

    2017-12-02 14:27:18 一.术语 Items:项,简记I Transaction:所有项的一个非空子集,简记T Dataset:Transaction的一个集合,简记D 关联规则: 一 ...

  3. 如何基于Netty处理粘包、拆包问题?

    涉及到相关重要组件: ByteToMessageDecoder MessageToMessageDecoder 这两个组件都实现了ChannelInboundHandler接口,这说明这两个组件都是用 ...

  4. 构建工具 Ant、Maven和Gradle

    构建工具的作用 依赖管理 测试,打包,发布 主流的构建工具 Ant:提供编译,测试,打包 Maven:在Ant的基础上提供了依赖管理和发布的功能 Gradle:在Maven的基础上使用Groovy管理 ...

  5. linux利用软件raid搭建iscsi存储

    分区:parted /dev/sdbmklabel gptmkpart primary ext4 0% 100%set 1 raid mdadm -Cv /dev/md0 -n 4 -l5 /dev/ ...

  6. 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。(System.Data)

    Sql server2012连接Sql server2008时出现的问题:已成功与服务器建立连接,但在登陆过程中发生错误.(provider:SSLProvider,error:0-接收到的消息异常, ...

  7. C++设计与声明——让接口容易被正确使用

    一个简答易错的例子 class Date { public Date(int month,int day,int year); } 一年后使用这个接口的时候,写了Date d(15,10,2015)或 ...

  8. ESET Smart Security – 免费90天(sv)

    Eset 活动很多,还有beta测试,几乎可以免费使用Eset.萨尔瓦多.免费活动,3个月免费ESS/EAV活动地址: 点此进入  填写表格,给你免费3个月的 ESS\EAV 许可证.官方网站: 点此 ...

  9. iOS KVC 和 KVO 区别简单总结

    KVC: key value coding,键值编码.是一种通过使用属性的名称(key)来间接访问对象属性的方法.这个方法可以不用通过 setter/getter 方法来访问对象的属性.该方法使用的实 ...

  10. Centos7 环境下开机 自启动服务(service) 设置的改变 (命令systemctl 和 chkconfig用法区别比较)

    参考文章:  <Linux 设置程序开机自启动 (命令systemctl 和 chkconfig用法区别比较)> http://blog.csdn.net/kenhins/article/ ...