2013-03-09 34 views
9

Vì vậy, giả sử chúng tôi muốn tạo một ứng dụng web giống như một ứng dụng gốc với "Thêm vào màn hình chính". Một trong những bước đầu tiên là tắt tính năng cuộn mặc định. Dễ dàng, phải không?iOS Tắt tính năng Cuộn trang bằng tính năng cuộn quá mức: chạm vào

// window or document 
window.addEventListener("touchmove", function(event) { 
    // no more scrolling 
    event.preventDefault(); 
}, false); 

Đó là tất cả tiền phạt và dandy cho đến khi bạn thêm overflow-scrolling vào danh sách kết hợp. Để chính xác, trên iOS, nó sẽ là -webkit-overflow-scrolling: touch.

/* #scrollable happens to be a ul */ 
#scrollable { 
    overflow-y: auto; 
    -webkit-overflow-scrolling: touch; 
} 

Bằng cách thêm ngăn sự kiện, cuộn được tăng tốc phần cứng trong vùng chứa không hoạt động, rõ ràng không phải là hiệu quả dự định.

Các giải pháp rõ ràng trông giống như sau:

// you could do this for multiple elements, of course 
var scrollable = document.querySelector("#scrollable"); 
scrollable.addEventListener("touchmove", function(event) { 
    // no more bubbling :) 
    event.stopPropagation(); 
}, false); 

giải pháp này giới thiệu một vấn đề, tuy nhiên, nếu bạn cố gắng để di chuyển sang trái hoặc phải trong #scrollable, nó quay ngược lại cho người nghe cuộn mặc định. Rõ ràng, sau đó, bạn nên theo dõi các sự kiện để xem sự kiện touchmove có đang theo dõi sang trái hoặc sang phải không? Thật không may, không, vì nó cũng sẽ, trong những trường hợp tôi không hoàn toàn hiểu, hãy hoàn nguyên về trình nghe cuộn mặc định khi cuộn dọc trong vùng chứa.

Bây giờ làm gì? Để làm cho vấn đề tồi tệ hơn, chúng tôi sẽ lý tưởng có thể xử lý click hoặc nhấp như các sự kiện trên cá nhân li s (đọc: touchstart):

var items = scrollable.querySelectorAll("#scrollable li"); 
for (var item = 0; item < items.length; item++) { 
    items[item].addEventListener("touchstart", function() { 
     // handle the touch start 
    }, false); 
} 

Để khắc phục vấn đề này, chúng ta có thể chuyển sang đơn giản là sử dụng click sự kiện, nhưng điều đó mặc định mục tiêu làm cho webapp "cảm thấy" có nguồn gốc do sự chậm trễ giữa khai thác và phản hồi. Để giải quyết việc này, chúng ta sẽ thêm một người biết lắng nghe sự kiện cho touchstarttouchend:

var items = scrollable.querySelectorAll("#scrollable li"); 
var activeItem = null, startTouch = null; 
for (var item = 0; item < items.length; item++) { 
    items[item].addEventListener("touchstart", function(event) { 
     startTouch = event.touches[0]; 
     activeItem = this; 
    }, false); 
    items[item].addEventListener("touchend", function(event) { 
     var touch = event.changedTouches[0]; 
     var deltaX = touch.pageX - startTouch.pageX 
     var deltaY = touch.pageY - startTouch.pageY; 
     // require the touchstart to be within 10 pixels of the touchend 
     if (deltaX * deltaX + deltaY * deltaY <= 100) 
      // handle "click" event 
    }, false); 
} 

Đó là tất cả tốt và tốt, nhưng chúng tôi vẫn chưa giải quyết được vấn đề với trang mặc định di chuyển chiếm quyền điều khiển một số touchmove sự kiện. Ý tưởng nào?

Trả lời

8

Hãy thử trao đổi xung quanh logic trong windowscrollable nghe yếu tố của bạn như vậy:

// window or document 
window.addEventListener("touchmove", function(event) { 
    if (!event.target.classList.contains('scrollable')) { 
    // no more scrolling 
    event.preventDefault(); 
    } 
}, false); 

// No special listeners needed on .scrollable elements 

Bằng cách này, bạn chỉ ngăn chặn mặc định khi cố gắng để di chuyển các yếu tố phi cuộn.

Bạn sẽ vẫn gặp sự cố ở đầu/cuối nội dung có thể cuộn bắt đầu kéo có thể khiến toàn bộ ứng dụng bị "thoát". Để khắc phục sự cố này, hãy xem Joe Lambert's ScrollFix.

Các vấn đề liên quan