Javascript CSS转换后触摸事件的Android 4 Chrome命中测试问题

Javascript CSS转换后触摸事件的Android 4 Chrome命中测试问题,javascript,android,css,google-chrome,touch,Javascript,Android,Css,Google Chrome,Touch,我在CSS转换和触摸事件命中测试的组合方面遇到了问题。这只在Android 4(稳定版和测试版)上的Chrome中为我复制。iOS Safari和带有触摸模拟的Chrome桌面似乎都运行良好 我几乎可以肯定这一定是一个bug,所以我想我主要是在这里寻找解决方法 问题是触摸的点击测试似乎只适用于元素在转换之前的位置,而不是最终位置。您可以在我的JSFIDLE上看到一个示例(仅在Android 4 Chrome上): jsfiddle: 全屏: 如果将蓝色框拖到屏幕的一半并松开,它将弹回到顶部。现在

我在CSS转换和触摸事件命中测试的组合方面遇到了问题。这只在Android 4(稳定版和测试版)上的Chrome中为我复制。iOS Safari和带有触摸模拟的Chrome桌面似乎都运行良好

我几乎可以肯定这一定是一个bug,所以我想我主要是在这里寻找解决方法

问题是触摸的点击测试似乎只适用于元素在转换之前的位置,而不是最终位置。您可以在我的JSFIDLE上看到一个示例(仅在Android 4 Chrome上):

jsfiddle: 全屏:

如果将蓝色框拖到屏幕的一半并松开,它将弹回到顶部。现在,如果再次尝试从页面的上半部分拖动,则不会显示任何触摸。触摸事件甚至不会在元素上触发。但是,如果尝试触摸元素的底部,则效果良好。然后,您可以尝试从底部向上移动它,观察命中测试不再在底部有效,而是在顶部有效

这就是我处理事件的方式:

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时,浏览器都会重新启动,最后一次这样做是在触发touchend事件之前。有两种方法可以解决这个问题:

选项1:您可以在body元素上设置一个touch处理程序,并检查touch事件的目标,以查看它是否正在接触红色块。保罗·刘易斯(Paul Lewis)对这种方法的建议

选项2:在文档上设置一个空的touch回调似乎也解决了这个问题-根据一些链接的bug报告,这会导致在主线程上进行命中测试,这是一个命中性能测试,但它会正确地计算命中目标

选项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:

我想我暂时已经在这方面解除了自己的障碍。从touchmove中删除innerHTML更新将停止命中目标的不良行为。我希望当我以后合法地需要更新元素中的内容时,这不会再次伤害我。
document.body.addEventListener('touchstart', function(){});
el.addEventListener(TRANSITION_END, function(e) {
    console.log("trans end - offsettop:" + el.offsetTop);
    el.style[TRANSITION] = '';
    el.innerHTML = 'Relayout like a boss!';
});