在上两篇文章【10行代码搞定移动web端自定义tap事件】【移动web端模拟hover效果】中分别对移动web端的自定义tap事件、模拟hover效果的原理进行了简单的说明。这篇文章主要把二者结合在了一块儿,解决了一些bug,使得总体效果更佳。web
以前的自定义tap没有考虑到双击、长按等使用场景(感谢 @超级小面包 的建议!),此次新增了langTap、doubleTap事件。模拟hover效果因为是独立于自定义tap的,效果有些小瑕疵,此次结合了tap,效果好了不少segmentfault
//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"); });
触发条件:当用户触摸屏幕的时间达到700ms时且未移动过code
//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);
触发条件:用户在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效果的原理在上两篇文章中都有说明,这里就再也不赘述了(主要是不知道该怎么描述了(-_-))。事件
文章有什么不对的地方,望你们指正。欢迎交流!rem