Javascript:除了使用 event.preventDefault() 之外,还有什么让 Chrome for Android 触发 touchmove 和 touchend 事件侦听器的解决方法吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20412982/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript: Any workarounds for getting Chrome for Android to fire off touchmove and touchend event listeners other than using event.preventDefault()?
提问by Kyle Weems
When using event listeners with the touchmove and touchend events, I can't get Chrome for Android to acknowledge those events unless I first use event.preventDefault(); earlier in the code. If I'm not wanting to block the default scroll functionality, is there any other workaround I can use to get Chrome for Android to acknowledge these events?
当使用带有 touchmove 和 touchend 事件的事件侦听器时,除非我首先使用 event.preventDefault();否则我无法让 Chrome for Android 确认这些事件;在代码的前面。如果我不想阻止默认滚动功能,是否还有其他解决方法可以让 Chrome for Android 确认这些事件?
Sample code:
示例代码:
$(document).ready(function () {
// Bind touch event listeners.
var elem = $('html').get(0);
elem.addEventListener('touchstart', function (e) { console.info('"touchstart" detected. Coordinates - ' + getCoord(e)); });
elem.addEventListener('touchmove', function (e) { console.info('"touchmove" detected. Coordinates - ' + getCoord(e)); });
elem.addEventListener('touchend', function (e) { console.info('"touchend" detected. Coordinates - ' + getCoord(e)); });
function getCoord(e) {
var touch = false;
if (e.touches.length > 0) {
touch = e.touches[0];
} else {
touch = e.changedTouches[0];
}
if (touch) {
return 'x: ' + touch.pageX + ', y: ' + touch.pageY;
}
}
Example fiddle here: http://jsfiddle.net/jQ2VS/1/
示例小提琴在这里:http: //jsfiddle.net/jQ2VS/1/
回答by Henry Chan
Google Chrome will fire a touchcancel
event about 200 milliseconds after touchstart
if it thinks the user is panning/scrolling and you do not call event.preventDefault()
.
谷歌Chrome浏览器会触发一个touchcancel
约后200毫秒时touchstart
,如果它认为用户平移/滚动和你不来电event.preventDefault()
。
Assuming that you want to intercept horizontal touch events and let vertical touch events cause panning/scrolling, a workaround would be:
假设您想拦截水平触摸事件并让垂直触摸事件导致平移/滚动,解决方法是:
- On
touchstart
, store the coordinates in a variable, and setiteration
to 0. - For each
touchmove
event, setiteration
toiteration
+1. - When
iteration
is equal to 4 (just a "magic number" I found to be reliable on my set-up), calculate the total touch offset deltas for x- and y- axes. EDIT: on mobile devices you'll only receive one touchmove without event.preventDefault() - If x-axis offset > y-axis offset * 3 then fire event.preventDefault(). (This ensures the the gesture is pretty much horizontal)
- On
touchstart
,将坐标存储在一个变量中,并设置iteration
为 0。 - 对于每个
touchmove
事件,设置iteration
为iteration
+1。 - 当
iteration
等于 4(只是我发现在我的设置中可靠的“幻数”)时,计算 x 轴和 y 轴的总触摸偏移增量。编辑:在移动设备上你只会收到一个没有 event.preventDefault() 的 touchmove - 如果 x 轴偏移 > y 轴偏移 * 3,则触发 event.preventDefault()。(这确保手势几乎是水平的)
The down-side for this is that user can only either swipe left/right or scroll up/down.
这样做的缺点是用户只能向左/向右滑动或向上/向下滚动。
回答by Giovanni Di Gregorio
Finally I found the solution (pure js) even in case you might want use it for swipe:
最后我找到了解决方案(纯 js),即使你可能想用它刷卡:
var swipe = function() {
var touchX, touchY, movX, movY, go;
function prevent(e){
e.preventDefault();
}
function start(e) {
go = false;
document.addEventListener("touchmove", prevent, false);
touchX = e.touches[0].pageX;
touchY = e.touches[0].pageY;
}
function move(e) {
movX = e.touches[0].pageX - touchX;
movY = e.touches[0].pageY - touchY;
if(!go) {
(Math.abs(movY) < Math.abs(movX)) ? go = true : stop(e);
} else {
/* *************** */
// cast your spell
/* *************** */
}
}
function stop(e) {
document.removeEventListener("touchmove", prevent, false);
}
document.addEventListener("touchstart", start, true);
document.addEventListener("touchmove", move, true);
document.addEventListener("touchend", stop, true);
document.addEventListener("touchleave", stop, true);
document.addEventListener("touchcancel", stop, true);
}
Hope this help.
希望这有帮助。
回答by Kinlan
The simplest answer is that you have to preventDefault on the first touchmove event otherwise they will be cancelled.
最简单的答案是您必须在第一个 touchmove 事件上防止默认,否则它们将被取消。
回答by Kinlan
I found that preventing the touchcancel worked fine.
我发现防止 touchcancel 工作正常。
回答by tnt-rox
The accepted answer is not correct.
接受的答案不正确。
On Android if preventDefault is not set on touchstart the device assumes native scrolling and no more touch events are sent to webview. If preventDefault is set all native scrolling is disabled.
在 Android 上,如果在 touchstart 上未设置 preventDefault,则设备假定本机滚动并且不再向 webview 发送触摸事件。如果设置了 preventDefault ,则禁用所有本机滚动。
There is a shim to provide swipe events with native scrolling here : https://github.com/TNT-RoX/android-swipe-shim
这里有一个 shim 提供带有本机滚动的滑动事件:https: //github.com/TNT-RoX/android-swipe-shim