5

CSS 変換とタッチ イベント ヒット テストの組み合わせに問題があります。これは、Android 4 (安定版およびベータ版) の Chrome でのみ再現されます。iOS Safari と、タッチ エミュレーションを備えた Chrome デスクトップはどちらも正常に動作しているようです。

これはバグに違いないとほぼ確信しているので、ここで主に回避策を探していると思います。

問題は、タッチのヒット テストが、最終的な位置ではなく、要素が変換前にあった場所でのみ機能するように見えることです。私の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 の変換に問題はありません。

助言がありますか?

4

1 に答える 1

9

これは Chrome の珍しいバグです。

基本的に、要素のヒット ターゲットは、ブラウザによるレイアウト パス中に記録されます。innerHTML を設定するたびに、ブラウザーは再レイアウトを行い、これが最後に行われるのは touchend イベントが発生する前です。それを回避する方法がいくつかあります。

オプション 1: body 要素にタッチ ハンドラーを設定し、タッチ イベントのターゲットをチェックして、赤いブロックに触れているかどうかを確認できます。このアプローチについてポール・ルイスに感謝します。

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!';
});

ここでバグ レポートを作成し、Rick Byers が関連するバグと追加情報をリンクしました: https://code.google.com/p/chromium/issues/detail?id=253456&thanks=253456&ts=1372075599

于 2013-06-26T08:33:25.280 に答える