在上两篇文章【10行代码搞定移动web端自定义tap事件】【移动web端模拟hover效果】中分别对移动web端的自定义tap事件、模拟hover效果的原理进行了简单的说明。这篇文章主要把两者结合在了一起,解决了一些bug,使得整体效果更佳。
之前的自定义tap没有考虑到双击、长按等使用场景(感谢 @超级小面包 的建议!),这次新增了langTap、doubleTap事件。模拟hover效果由于是独立于自定义tap的,效果有些小瑕疵,这次结合了tap,效果好了很多
效果预览
核心代码
//tap定时器
var timer_tap;
//langTap定时器
var timer_langTap;
//自定义tap、doubleTap、langTap
$(document).on("touchstart", function (e) {
var $target = $(e.target);
var tapData = $target.data("tapData");
//不处理含有disable class的对象
if ($target.hasClass("disable")) return;
//状态信息
tapData = tapData ? tapData : {};
tapData.state = "start";
tapData.isMoved = 0;
tapData.preTouchStartTime = tapData.touchStartTime ? tapData.touchStartTime : null;
tapData.touchStartTime = new Date().getTime();
//doubleTap
if(tapData.preTouchStartTime && tapData.touchStartTime - tapData.preTouchStartTime < 250) {
//doubleTap
tapData.doubleTapTime = tapData.touchStartTime;
//记录信息
$target.data("tapData", tapData);
//清除timer_tap
clearTimeout(timer_tap);
return;
}
//langTap
timer_langTap = setTimeout(function() {
var tapData = $target.data("tapData");
if(tapData.state != "start") return;
$target.trigger("langTap");
if(tapData.$hover) tapData.$hover.removeClass("active");
}, 700);
//寻找$hover对象
var $hover;
if($target.hasClass("action-btn")) {
$hover = $target;
}else {
$target.parents().each(function() {
if($(this).hasClass("action-btn")) $hover = $hover ? $hover : $(this);
});
}
tapData.$hover = $hover;
//记录信息
$target.data("tapData", tapData);
//点击效果
if(!$hover) return;
//延迟78ms
setTimeout(function() {
var tapData = $target.data("tapData");
//移动过
if(tapData.isMoved != 0) return;
//添加点击效果
tapData.$hover.addClass("active");
}, 78);
});
$(document).on("touchmove", function (e) {
var $target = $(e.target);
var tapData = $target.data("tapData");
//不处理含有disable class的对象
if ($target.hasClass("disable")) return;
//记录信息
tapData.state = "move";
tapData.isMoved = 1;
tapData.touchStartTime = 0;
$target.data("tapData", tapData);
//点击效果
if(tapData.$hover) tapData.$hover.removeClass("active");
});
$(document).on("touchend", function (e) {
var $target = $(e.target);
var tapData = $target.data("tapData");
//不处理含有disable class的对象
if ($target.hasClass("disable")) return;
//清除长按倒计时
clearTimeout(timer_langTap);
//记录信息
tapData.state = "end";
$target.data("tapData", tapData);
//是否移动过
if (tapData.isMoved == 1) return;
//触摸时间
var duration = new Date().getTime() - tapData.touchStartTime;
//doubleTap
if(tapData.doubleTapTime == tapData.touchStartTime) {
//触发doubleTap
$target.trigger("doubleTap");
if(tapData.$hover) tapData.$hover.removeClass("active");
//重置开始点击事件(防止连续触发doubleTap)
tapData.touchStartTime = 0;
$target.data("tapData", tapData);
return;
}
//tap
if(duration <= 250) {
//点击效果持续250ms
timer_tap = setTimeout(function() {
//tap
$target.trigger("tap");
if(tapData.$hover) tapData.$hover.removeClass("active");
}, 250 - duration);
return;
}
//触摸时间在250ms到700ms之间
if(tapData.$hover) tapData.$hover.removeClass("active");
});
$(document).on("touchcancel", function (e) {
var $target = $(e.target);
var tapData = $target.data("tapData");
if(tapData.$hover) tapData.$hover.removeClass("active");
});
新增内容
langTap
触发条件:当用户触摸屏幕的时间达到700ms时且未移动过
//langTap
timer_langTap = setTimeout(function() {
var tapData = $target.data("tapData");
if(tapData.state != "start") return;
$target.trigger("langTap");
if(tapData.$hover) tapData.$hover.removeClass("active");
}, 700);
doubleTap
触发条件:用户在250ms内连续触摸屏幕两次
//doubleTap
if(tapData.preTouchStartTime && tapData.touchStartTime - tapData.preTouchStartTime < 250) {
//doubleTap
tapData.doubleTapTime = tapData.touchStartTime;
//记录信息
$target.data("tapData", tapData);
//清除timer_tap
clearTimeout(timer_tap);
return;
}
其他
自定义tap和模拟hover效果的原理在上两篇文章中都有说明,这里就不再赘述了(主要是不知道该怎么描述了(-_-))。
文章有什么不对的地方,望大家指正。欢迎交流!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。