如何绑定 Mousedown 和 Touchstart,但不响应两者?安卓、jQuery
Posted
技术标签:
【中文标题】如何绑定 Mousedown 和 Touchstart,但不响应两者?安卓、jQuery【英文标题】:How to bind both Mousedown and Touchstart, but not respond to both? Android, JQuery 【发布时间】:2012-11-19 07:19:55 【问题描述】:在一个也可以在移动设备上查看的网站上工作,并且需要在 touchstart 和 mousedown 上绑定一个操作。
看起来像这样
$("#roll").bind("mousedown touchstart", function(event)
someAction();
它在 Iphone 上运行良好,但在 android 上它响应两次。
event.stopPropagation();
event.preventDefault();
添加此代码修复了 Android Chrome 的问题,但不适用于 Android 默认浏览器。还有其他可以解决所有android问题的技巧吗?
【问题讨论】:
event.preventDefault() 应该停止 mousedown 事件。这个问题很老了,所以希望它现在得到解决。我遇到了同样的问题,结果发现是 jquery touchpunch 造成的。 这个相同的问题可能对某人的帮助不仅仅是在这里回答:***.com/questions/7018919/… 【参考方案1】:element.on('touchstart mousedown', function(e)
e.preventDefault();
someAction();
);
preventDefault
取消事件,as per specs
您会获得 touchstart,但一旦您取消它,您将不再获得 mousedown。与接受的答案相反,您无需致电stopPropagation
,除非您需要。即使取消,该事件也会正常传播。浏览器会忽略它,但你的钩子仍然可以工作。
Mozilla agrees with me 在这个:
在 touchstart 或一系列的第一个 touchmove 事件上调用 preventDefault() 可防止相应的鼠标事件触发
编辑:我刚刚再次阅读了这个问题,你说你已经这样做了,它没有修复 Android 默认浏览器。不确定接受的答案有何帮助,因为它基本上做同样的事情,只是以更复杂的方式和一个事件传播错误(touchstart 不传播,但 click 传播)
【讨论】:
在 android 上,我得到“忽略取消可取消的 touchmove 事件的尝试=false,例如因为滚动正在进行中且无法中断” 你可能需要 addEventListener('touchstart', FUNCTION, passive: false); 可以,但是你甚至不能通过滑动来滚动页面。【参考方案2】:我一直在使用这个功能:
//touch click helper
(function ($)
$.fn.tclick = function (onclick)
this.bind("touchstart", function (e)
onclick.call(this, e);
e.stopPropagation();
e.preventDefault();
);
this.bind("click", function (e)
onclick.call(this, e); //substitute mousedown event for exact same result as touchstart
);
return this;
;
)(jQuery);
更新:修改答案以同时支持鼠标和触摸事件。
【讨论】:
请注意,Windows 8 上的 Chrome 和 Firefox 将在检测到触摸屏时启用触摸事件。因此用户可以在鼠标和触摸输入之间切换。使用此代码,鼠标事件将被忽略。 @gregers 你是对的,也是错的。 Windows 8 确实支持 Touch 和 Mouse 事件,但是在触摸时您可以取消“虚拟”鼠标事件以仅处理触摸,它不会影响 REAL 鼠标事件,因为它们不会触发 Touch 事件。 @daniel.gindi 我的评论是针对此答案的先前版本:***.com/posts/14202543/revisionstouchstart
等价于mousedown
而不是click
。单击需要用户按下按钮。我看不出这有什么完全相同的结果。
您将如何解除此事件的绑定?说是否要暂时添加侦听器,然后停止触发事件?【参考方案3】:
考虑到 gregers 对 win8 和 chrome/firefox 的评论,skyisred 的评论看起来并没有那么愚蠢(:P @ all the haters) 虽然我宁愿使用黑名单而不是他建议的白名单,仅将 Android 排除在触摸绑定之外:
var ua = navigator.userAgent.toLowerCase(),
isAndroid = ua.indexOf("android") != -1,
supportsPointer = !!window.navigator.msPointerEnabled,
ev_pointer = function(e) ... , // function to handle IE10's pointer events
ev_touch = function(e) ... , // function to handle touch events
ev_mouse = function(e) ... ; // function to handle mouse events
if (supportsPointer) // IE10 / Pointer Events
// reset binds
$("yourSelectorHere").on('MSPointerDown MSPointerMove MSPointerUp', ev_pointer);
else
$("yourSelectorHere").on('touchstart touchmove touchend', ev_touch); // touch events
if(!isAndroid)
// in androids native browser mouse events are sometimes triggered directly w/o a preceding touchevent (most likely a bug)
// bug confirmed in android 4.0.3 and 4.1.2
$("yourSelectorHere").on('mousedown mousemove mouseup mouseleave', ev_mouse); // mouse events
顺便说一句:我发现鼠标事件并不总是被触发(如果使用了 stopPropagation 和 preventDefault),特别是我只注意到一个额外的 mousemove 直接在 touchend 事件之前......真的很奇怪的错误,但上面的代码为我修复了它跨所有平台(测试过的 OSX、Win、ios 5+6、Android 2+4,每个都带有本机浏览器、Chrome、Firefox、IE、Safari 和 Opera,如果可用)。
【讨论】:
这太冗长了,你能想象每次 IE 发布新版本时都要维护所有这些吗?【参考方案4】:哇,这个问题和相关问题有这么多答案,但没有一个对我有用(Chrome、mobil responsive、mousedown + touchstart)。但是这个:
(e) =>
if(typeof(window.ontouchstart) != 'undefined' && e.type == 'mousedown') return;
// do anything...
【讨论】:
务实的解决方案:)【参考方案5】:使用此代码修复
var mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
var start = mobile ? "touchstart" : "mousedown";
$("#roll").bind(start, function(event)
【讨论】:
-1:使用特征检测(如 Joshua 的回答)而不是 UA 检测。 这是最好的答案,也是唯一有效的答案。约书亚的回答不使用特征检测。您需要检测的唯一功能是 android 当前的怪癖。如果您检测到具有触摸事件的功能,那么它将禁用触摸屏笔记本电脑的鼠标。 e.preventDefault() 在 android 上失败。 触摸和鼠标的设备怎么样? 这也不能正常工作。我已经用类范围和没有范围进行了测试,那么每种方式都有自己的问题。无论您如何尝试使用touchstart
或mousedown
触发函数,在类范围内使用此代码只会触发mousedown
。如果没有范围,它会一直触发您第一次触发的一个结果。【参考方案6】:
我建议你试试jquery-fast-click。我在这个问题上尝试了另一种方法和others。每个人都解决了一个问题,并引入了另一个问题。快速点击首次在 Android、ios、桌面和桌面触摸浏览器上运行(呻吟)。
【讨论】:
【参考方案7】:编写此代码并添加j查询punch touch js。它将使用触摸事件模拟鼠标事件
function touchHandler(event)
var touches = event.changedTouches,
first = touches[0],
type = "";
switch(event.type)
case "touchstart": type = "mousedown"; break;
case "touchmove": type="mousemove"; break;
case "touchend": type="mouseup"; break;
default: return;
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1,
first.screenX, first.screenY,
first.clientX, first.clientY, false,
false, false, false, 0/*left*/, null);
first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
function init()
document.addEventListener("touchstart", touchHandler, true);
document.addEventListener("touchmove", touchHandler, true);
document.addEventListener("touchend", touchHandler, true);
document.addEventListener("touchcancel", touchHandler, true);
【讨论】:
【参考方案8】:这个原生解决方案最适合我:
-
将
touchstart
事件添加到全局touch = true
的文档设置中。
在 mousedown/touchstart 处理程序中,在检测到触摸屏时阻止所有 mousedown 事件:if (touch && e.type === 'mousedown') return;
【讨论】:
【参考方案9】:这是一个非常古老的问题,但我遇到了同样的问题,并找到了另一个解决方案,它不stopPropagation()
、preventDefault()
或嗅探设备类型。我在这个解决方案上工作的假设是设备同时支持触摸和鼠标输入。
说明:当触发触摸时,事件顺序为1)touchstart
2)touchmove
3)touchend
4)mousemove
5)mousedown
6)mouseup
7)@987654329 @。基于此,我们将标记从touchstart
(链中第一个)到click
(链中最后一个)的触摸交互。如果mousedown
在此触摸交互之外注册,则可以安全地拾取。
下面是 Dart 中的逻辑,在 js 中应该是非常可复制的。
var touchStarted = false;
document.onMouseDown.listen((evt)
if (!touchStarted) processInput(evt);
);
document.onClick.listen((evt)
touchStarted = false;
);
document.onTouchStart.listen((evt)
touchStarted = true;
processInput(evt);
);
如您所见,我的听众位于document
。因此,重要的是我不要stopPropagation()
或preventDefault()
这些事件,以便它们可以冒泡到其他元素。这个解决方案帮助我挑选出一个交互来采取行动,希望它也能帮助你!
【讨论】:
【参考方案10】:我认为最好的方法是:
var hasTouchStartEvent = 'ontouchstart' in document.createElement( 'div' );
document.addEventListener( hasTouchStartEvent ? 'touchstart' : 'mousedown', function( e )
console.log( e.touches ? 'TouchEvent' : 'MouseEvent' );
, false );
【讨论】:
那么我的鼠标在我的触摸屏笔记本电脑上就不能工作了。如果你为 mousedown 添加另一个事件,android 将在触摸时触发。 大多数新笔记本电脑也支持触摸屏,所以会有这些事件..不要这样做!以上是关于如何绑定 Mousedown 和 Touchstart,但不响应两者?安卓、jQuery的主要内容,如果未能解决你的问题,请参考以下文章