2013-05-22 20 views
5

CSSトランスフォームとタッチイベントヒットテストの組み合わせに問題があります。これはAndroid 4(安定版とベータ版)のChromeでのみ再生できます。 iOS Safariとタッチエミュレーションを備えたChromeデスクトップの両方が正常に動作しているようです。Android 4 CSS変換後のタッチイベントの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に変換して何の問題もありません。

提案がありますか?

+0

私はこれについて当面はいくらかブロックしていると思います。 touchmoveからinnerHTMLアップデートを削除すると、ヒットターゲットのバッドネスが停止します。後でエレメントの内部でコンテンツを正当に更新する必要があるときに、これが私をかみ傷から戻さないように願っています。 –

答えて

8

これは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; 
    } 

    .... 

OPTION 2:同様の問題を解決するよう文書で空のタッチコールバックを設定します - リンクバグレポートの一部によると、これはヒットテストは上で行うことになりメインスレッドはパフォーマンスでヒットしますが、ヒットしたターゲットを適切に計算します。

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

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

OPTION 3:セットのinnerHTMLの遷移が再レイアウトを強制的に終了した後:

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

私はここにバグレポートを作成したとリック・バイヤーズは、関連するリンクされています追加の情報を持つバグ:https://code.google.com/p/chromium/issues/detail?id=253456&thanks=253456&ts=1372075599

+1

「OPTION 2」は魅力的な作品です。ありがとうございます。 –