2013-04-11 137 views
13

我試圖建立一個網頁,感知來自用戶的觸摸和拖動和畫布上的對象。Android瀏覽器:touchcancel被觸發儘管touchmove已阻止默認

所以我在做這樣的事情:

var touchStart = function(e) { 
    e.preventDefault(); 
    // Do stuff 
} 
var touchMove = function(e) { 
    e.preventDefault(); 
    console.log("Touch move"); 
    // Move objs 
} 
var touchEnd = function(e) { 
    e.preventDefault(); 
    console.log("Touch start!"); 
    // clean up stuff 
} 
var touchCancel = function(e) { 
    e.preventDefault(); 

    // Oh NO touch cancel! 
    console.log("Touch cancel!"); 

} 
bindElemOrig.addEventListener('touchstart', touchStart, false); 
bindElemOrig.addEventListener('touchmove', touchStart, false); 
bindElemOrig.addEventListener('touchend', touchStart, false); 
bindElemOrig.addEventListener('touchcancel', touchStart, false); 

它正常工作,直到某一點。

的問題是,當我加載了太多OBJ文件,在我看來,該touchmove時間過長迴應,並touchcancel被觸發。問題是,touchcancel被觸發,我不再收到任何更多touchmove的事件,我不能再感覺到運動了。

有沒有人遇到過這個問題?我知道Android中的錯誤,您必須致電preventDefaulttouchend event in ios webkit not firing?),但在這種情況下,由於存儲器負擔似乎不起作用。

謝謝!

+1

我在Android 2.3上遇到同樣的問題。 Android 4+似乎沒問題。你有沒有發現這個話題? – dioslaska 2013-06-20 12:18:43

+0

@dioslaska shim @ https:// github。com/TNT-RoX/android-swipe-shim – 2014-08-06 08:37:15

+0

爲了將來的參考,這裏的答案完美的作品:http://stackoverflow.com/questions/10367854/html5-android-touchcancel – 2015-07-24 20:26:40

回答

2

此問題可能是由於Chrome/Android中的錯誤(功能?)引起的。見this bug report

這個測試證明的行爲(JSFiddle):

<!DOCTYPE html> 
<html> 
    <head> 
    <title></title> 
    <script> 
     var delay = 200; 

     var haltEvent = function(event) { 
     event.preventDefault(); 
     event.stopPropagation(); 
     }; 

     var pause = function() { 
     var startTime = new Date().getTime(); 

     while (new Date().getTime() < startTime + delay); 
     }; 

     window.addEventListener('load', function() { 
     var target = document.querySelector('#target'); 
     var status = document.querySelector('#status'); 

     target.addEventListener('touchstart', function(event) { 
      haltEvent(event); 
      status.innerHTML = '[touchstart]'; 
     }, true); 

     target.addEventListener('touchmove', function(event) { 
      pause(); 
      haltEvent(event); 
      status.innerHTML = '[touchmove]'; 
     }, true); 

     target.addEventListener('touchend', function(event) { 
      status.innerHTML = '[touchend]'; 
     }, true); 

     target.addEventListener('touchcancel', function(event) { 
      status.innerHTML = '[touchcancel]'; 
     }, true); 
     }); 
    </script> 
    <style> 
     #target { 
     background-color: green; 
     height: 300px; 
     } 

     #status { 
     text-align: center; 
     } 
    </style> 
    </head> 
    <body> 
    <div id="target"></div> 
    <p id="status">[]</p> 
    </body> 
</html> 

我沒有找到touchcancel事件是隨機發射。相反,只要從touchmove事件處理程序返回大約200毫秒時就會觸發它。

+0

我解決綁定touchcancel touchend – 2014-08-06 08:25:56

+7

請解釋「我通過綁定touchCancel來解決問題」 – FlavorScape 2014-08-12 07:23:33

3

這樣

var touchMove = function(e) { 
    e.preventDefault(); 
    setTimeout(function(){ 
     console.log("Touch move"); 
    // Move objs 

    }) 
} 

使用的setTimeout來包裝你的邏輯在touchmove可以解決這個問題

0

Touchcancel專門採取觸摸事件的控制,並進行定期的瀏覽器操作,如平移或縮放後一個非常小的觸摸和移動動作(近20px,取決於瀏覽器)。

你唯一的選擇,其一是:

  1. 切換到指針事件和使用touch-action CSS屬性as explained here到 防止pointercancel燒製而成(建議,但需要使用Android 5+)
  2. 添加event.preventDefault()內您的touchmove事件處理程序,但這也將禁用任何默認操作,如滾動,平移,縮放等。

您不能在touchcancel函數中取消或preventDefault(),因爲這樣做太遲了;瀏覽器已經停止收聽touchmove事件。這是設計,而不是一個錯誤。