2013-04-11 19 views
13

Tôi đang cố gắng xây dựng một trang web cảm nhận được cảm ứng từ người dùng và kéo và đối tượng dọc theo canvas.Trình duyệt Android: touchcancel đang được kích hoạt mặc dù touchmove đã chặnDefault

Vì vậy, tôi đang làm một cái gì đó như thế này:

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); 

Nó hoạt động tốt cho đến một lúc nào đó.

Vấn đề là ngay sau khi tôi nạp quá nhiều objs, có vẻ như với tôi rằng touchmove mất quá nhiều thời gian để trả lời, và touchcancel được kích hoạt. Vấn đề là ngay sau khi touchcancel được kích hoạt, tôi không nhận được thêm bất kỳ sự kiện nào khác nữa, và tôi không thể cảm nhận được chuyển động nữa.

Có ai phải đối mặt với vấn đề này không? Tôi biết về các lỗi trong Android, nơi bạn phải gọi ngăn chặnDefault (touchend event in ios webkit not firing?) nhưng trên trường hợp này có vẻ như nó không hoạt động vì gánh nặng bộ nhớ.

Cảm ơn bạn!

+1

Tôi đang gặp sự cố tương tự trên Android 2.3. Android 4+ có vẻ ổn. Bạn có tìm thấy gì về chủ đề này không? – dioslaska

+0

@dioslaska shim @ https: // github.com/TNT-RoX/android-swipe-shim –

+0

Để tham khảo sau này, câu trả lời ở đây hoạt động hoàn hảo: http://stackoverflow.com/questions/10367854/html5-android-touchcancel –

Trả lời

2

Sự cố này có thể do lỗi (tính năng?) Trong Chrome/Android. Xem this bug report.

thử nghiệm này cho thấy hành vi (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> 

Tôi không tìm thấy sự kiện touchcancel để bị sa thải một cách ngẫu nhiên. Thay vào đó, nó được kích hoạt bất cứ khi nào nó mất ~ 200 ms để trở về từ một trình xử lý sự kiện touchmove.

+0

Tôi giải quyết bằng cách liên kết touchcancel để chạm vào –

+7

vui lòng giải thích "Tôi giải quyết bằng cách liên kết touchcancel để chạm vào" – FlavorScape

3

như

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

    }) 
} 

sử dụng setTimeout này để quấn bạn logic trong touchmove có thể giải quyết vấn đề này

0

Touchcancel được thiết kế đặc biệt để kiểm soát các sự kiện liên lạc và thực hiện các hành động trình duyệt thông thường như chảo hoặc zoom sau một thao tác chạm và di chuyển rất nhỏ (gần 20px, tùy thuộc vào trình duyệt).

lựa chọn duy nhất của bạn là để một trong hai:

  1. Đổi thành Sự kiện Pointer và sử dụng tài sản touch-action CSS as explained here để ngăn chặn pointercancel từ bắn (nhưng yêu cầu phải Android 5 +)
  2. Thêm event.preventDefault() bên trong trình xử lý sự kiện touchmove của bạn, nhưng thao tác này cũng sẽ tắt mọi hành động mặc định như cuộn, xoay, thu phóng, v.v.

Bạn không thể áp dụng để hủy hoặc preventDefault() bên trong một hàm touchcancel bởi vì nó sẽ quá muộn cho điều đó; trình duyệt đã ngừng nghe sự kiện touchmove. Điều này là do thiết kế, không phải là một lỗi.