安卓4.0浏览器击中触摸事件检测问题的CSS变换后 [英] Android 4 Chrome hit testing issue on touch events after CSS transform

查看:482
本文介绍了安卓4.0浏览器击中触摸事件检测问题的CSS变换后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用CSS转换和触摸事件的组合问题命中测试。这只有在Chrome浏览器上的Andr​​oid 4.0(稳定和β)抄录给我。 iOS的Safari浏览器,以及Chrome浏览器桌面触摸仿真似乎一切工作的罚款。

I'm having issues with the combination of CSS transforms and touch event hit testing. This only reproduces for me in Chrome on Android 4 (stable and beta). iOS Safari, as well as Chrome desktop with touch emulation both appear to be working fine.

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

I'm almost positive this has to be a bug, so I think I'm mostly looking for workarounds here.

问题是,点击测试触摸似乎只工作在那里的元素是以前的转换,而不是最终位置。你可以看到我的jsfiddle(仅适用于安卓4.0浏览器)的一个例子:

The issue is that hit testing for touch only seems to work for where the element was before the transform, not the final position. You can see an example on my jsfiddle (only on Android 4 Chrome):

的jsfiddle: http://jsfiddle.net/LfaQq/ 全屏: http://jsfiddle.net/LfaQq/embedded/result/

jsfiddle: http://jsfiddle.net/LfaQq/ full screen: http://jsfiddle.net/LfaQq/embedded/result/

如果您拖动蓝色框半路屏幕并释放它会弹回顶端。现在,如果你尝试从页面的上半部分又拖着,没有触摸将注册。触摸事件,甚至不开的元素。但是,如果你试图触摸元件的底部,它工作正常。然后,您可以尝试将它从底部,并观察到命中测试不再在底部的作品,但作品放在最上面。

If you drag the blue box half way down the screen and release it will snap back to the top. Now, if you try dragging from the top half of the page again, no touch will register. The touch events aren't even fired on the element. However, if you attempt to touch the bottom of the element, it works fine. You can then try moving it up from the bottom, and observing that hit testing no longer works on the bottom, but works on the top.

这是我如何处理事件:

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的转换的任何问题,因为这些不应被反正检测到的新的一面。

I don't have any problems with the transforms in touchmove, as those aren't new touches to be detected anyways.

有什么建议?

推荐答案

这是在Chrome中一个不寻常的bug。

This is an unusual bug in Chrome.

从本质上讲命中目标元素在一个布局传递由浏览器记录。每次设置innerHTML的时候,浏览器会重新布局和上一次做到这一点,是touchend事件被触发之前。有周围几个方面:

Essentially the hit targets for an element is recorded during a layout pass by the browser. Each time you set innerHTML, the browser will relayout and the last time this is done, is before the touchend event is fired. There are a couple of ways around it:

选项1:您可以设置body元素上的触摸处理程序,并检查触摸事件的目标,看它是否接触到红块。提示帽保罗·刘易斯对这种做法的。

OPTION 1: You can set a touch handler on the body element and check the target of touch event to see if it is touching the red block. Tip of the cap to Paul Lewis for this approach.

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:设置该文件的空触摸回调似乎解决的问题,以及 - 根据一些链接的错误报告,这将导致命中测试要在主线程这是对性能的一击,但上完成它正确地计算命中目标。

OPTION 2: Set an empty touch callback on the document seems to fix the problem as well - according to some of the linked bug reports, this causes the hit testing to be done on the main thread which is a hit on performance but it properly calculates the hit targets.

http://jsfiddle.net/LfaQq/2/

document.body.addEventListener('touchstart', function(){});

选项3:设置innerHTML的转型已经结束强制重新布局后:

OPTION 3: Set innerHTML after the transition has ended to force a relayout:

el.addEventListener(TRANSITION_END, function(e) {
    console.log("trans end - offsettop:" + el.offsetTop);
    el.style[TRANSITION] = '';
    el.innerHTML = 'Relayout like a boss!';
});

我已经创建了一个错误报告在这里和里克·拜尔斯已链接到与其他信息相关的错误:<一href="https://$c$c.google.com/p/chromium/issues/detail?id=253456&thanks=253456&ts=1372075599">https://$c$c.google.com/p/chromium/issues/detail?id=253456&thanks=253456&ts=1372075599

这篇关于安卓4.0浏览器击中触摸事件检测问题的CSS变换后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆