Android 4 Chrome在CSS转换后的触摸事件命中测试问题
Android 4 Chrome hit testing issue on touch events after CSS transform
我对CSS转换和触摸事件命中测试的组合有问题。这只在Android 4(稳定版和测试版)的Chrome中重现。iOS Safari,以及Chrome桌面触摸模拟似乎都工作得很好。
我几乎可以肯定这是一个bug,所以我想我主要是在寻找解决方法。
问题在于touch的hit测试似乎只适用于元素在转换之前的位置,而不是最终位置。你可以在我的jsfiddle上看到一个例子(仅在Android 4 Chrome上):
jsfiddle: http://jsfiddle.net/LfaQq/全屏:http://jsfiddle.net/LfaQq/embedded/result/
如果你把蓝色盒子拖到屏幕的一半,然后松开它,它会弹回顶部。现在,如果你再次尝试从页面的上半部分拖动,触摸将不会被记录下来。触摸事件甚至不会在元素上触发。但是,如果您尝试触摸元素的底部,则可以正常工作。然后你可以尝试将它从底部向上移动,并观察到命中测试不再在底部工作,而是在顶部工作。
我是这样处理这些事件的:
function handleTouch(e) {
console.log("handle touch")
e.preventDefault();
switch(e.type){
case 'touchstart':
console.log("touchstart");
touchOriginY = e.targetTouches[0].screenY;
break;
case 'touchmove':
console.log("touchmove");
el.innerHTML = e.targetTouches[0].screenY;
var p = e.targetTouches[0].screenY - touchOriginY;
el.style[TRANSFORM] = 'translate3d(0,' + p + 'px' + ',0)';
break;
case 'touchcancel':
console.log("touchcancel");
// Fall through to touchend
case 'touchend':
//console.log("touchend");
//el.style[TRANSITION] = '.4s ease-out';
el.style[TRANSFORM] = 'translate3d(0,0,0)';
break;
}
}
el.addEventListener('touchstart', handleTouch);
el.addEventListener('touchend', handleTouch);
el.addEventListener('touchmove', handleTouch);
el.addEventListener(TRANSITION_END, function(e) {
console.log("transition end")
el.style[TRANSITION] = '';
});
我对touchmove中的转换没有任何问题,因为这些都不是要检测的新触摸。
有什么建议吗?
这是Chrome中不常见的错误。
基本上,元素的命中目标是在浏览器的布局传递过程中记录的。每次设置innerHTML时,浏览器都会重新布局,最后一次这样做是在触发触摸端事件之前。有几种方法可以绕过它:
选项1:你可以在body元素上设置一个触摸处理程序,并检查触摸事件的目标,看看它是否正在触摸红色块。保罗·刘易斯(Paul Lewis)用这种方法向他致敬。
http://jsfiddle.net/FtfR8/5/var el = document.body;
var redblock = $('.splash-section');
function handleTouch(e) {
console.log("handle touch")
if(e.target != redblock) {
return;
}
....
选项2:在文档上设置一个空的触摸回调似乎也解决了这个问题-根据一些链接的错误报告,这导致命中测试在主线程上完成,这是对性能的打击,但它正确地计算命中目标。
http://jsfiddle.net/LfaQq/2/document.body.addEventListener('touchstart', function(){});
选项3:在过渡结束后设置innerHTML来强制布局:
el.addEventListener(TRANSITION_END, function(e) {
console.log("trans end - offsettop:" + el.offsetTop);
el.style[TRANSITION] = '';
el.innerHTML = 'Relayout like a boss!';
});
我在这里创建了一个bug报告,Rick Byers已经链接到一个相关的bug,并提供了额外的信息:https://code.google.com/p/chromium/issues/detail?id=253456&thanks=253456&ts=1372075599
- 谷歌地图劫持了iphone's滚动(触摸事件)-如何恢复
- 如何在jquery中找到鼠标滚轮/触摸移动事件的走向
- 如何使用纯javascript的移动触摸事件
- 触摸启动事件未在iframe iOS 6中启动
- 如何检测滚动事件是否像在触摸设备上一样只触发一次
- 触摸滑动所有事件
- 移动定时触摸事件
- 模拟html5的触摸事件
- Phonegap/Cordova:如何添加Javascript多点触摸事件
- 如何在AngularJS中监听点击事件,而不是触摸事件
- 我可以让我的网站的内容可编辑区域对安卓股票浏览器上的触摸事件更敏感吗
- 当鼠标也在触摸另一个元素时,d3.js鼠标悬停事件未被触发
- 在 Firefox 中“解析”触摸事件
- 将触摸事件转换为鼠标事件仅每秒有效一次
- 在移动 Safari 上向下拖动时,触摸事件停止触发 - iPad HTML5
- 如何在 javascript 中触发触摸事件
- 为什么触摸事件不在手指按压的中间
- 如何启用离子多点触摸事件
- JavaScript事件.触摸数组
- D3鼠标事件触摸事件,即点击->支持触摸事件