2013-06-03 27 views
10

Dưới Mobile Safari, có thể cho phép một vị trí hoàn toàn được định vị div để cuộn mà không cho phép toàn bộ trang cuộn lên và xuống khi cuộn đến các cạnh (cuộn đàn hồi)?ngăn di chuyển toàn trang iOS

Dưới đây là một ví dụ làm việc tối thiểu của vấn đề tôi phải đối mặt:

<!doctype html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> 
    <meta name="apple-mobile-web-app-capable" content="yes" /> 
    <style> 
     * { 
      margin: 0; 
      padding: 0; 
      box-sizing: border-box; 
     } 
     #a, #b { 
      position: absolute; 
      top: 0; 
      left: 0; 
      height: 100%; 
      padding: 10px; 
      overflow: auto; 
     } 
     #a { 
      width: 80px; 
      background: #f00; 
     } 
     #b { 
      background: #00f; 
      left: 80px; 
      width: 100%; 
     } 
    </style> 
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> 
    <script> 
     function pdcb(e) { 
      e.preventDefault(); 
     } 
     function npcb(e) { 
      e.stopPropagation(); 
     } 
     $(document).on('touchstart touchmove', pdcb). 
        on('touchstart touchmove', '.scrollable', npcb); 
    </script> 
</head> 
<body> 
    <div id="a" class="scrollable"> 
     This<br> 
     should<br> 
     be<br> 
     scrollable<br> 
     but<br> 
     not<br> 
     scroll<br> 
     the<br> 
     whole<br> 
     page<br> 
     This<br> 
     should<br> 
     be<br> 
     scrollable<br> 
     but<br> 
     not<br> 
     scroll<br> 
     the<br> 
     whole<br> 
     page<br> 
     This<br> 
     should<br> 
     be<br> 
     scrollable<br> 
     but<br> 
     not<br> 
     scroll<br> 
     the<br> 
     whole<br> 
     page<br> 
     This<br> 
     should<br> 
     be<br> 
     scrollable<br> 
     but<br> 
     not<br> 
     scroll<br> 
     the<br> 
     whole<br> 
     page<br> 
     This<br> 
     should<br> 
     be<br> 
     scrollable<br> 
     but<br> 
     not<br> 
     scroll<br> 
     the<br> 
     whole<br> 
     page<br> 
    </div> 
    <div id="b"> 
     this should never scroll 
    </div> 
</body> 
</html> 

Giải pháp:

$(document).on('touchmove', function(e) { 
    e.preventDefault(); 
}).ready(function() { 
    $(".scrollable").on('touchstart', function(e) { 
     this.allowUp = (this.scrollTop > 0); 
     this.allowDown = (this.scrollTop < this.scrollHeight - this.clientHeight); 
     this.prevTop = null; 
     this.prevBot = null; 
     this.lastY = e.originalEvent.pageY; 
    }).on('touchmove', function(e) { 
     var event = e.originalEvent; 
     var up = (event.pageY > this.lastY), down = !up; 
     this.lastY = event.pageY; 

     if ((up && this.allowUp) || (down && this.allowDown)) 
      event.stopPropagation(); 
     else 
      event.preventDefault(); 
    }); 
}); 
+1

không, không phải là một trùng lặp. có hai thay đổi 'div'. –

+2

Mọi người đánh dấu mục này là trùng lặp - Đây không phải là câu hỏi trùng lặp - câu hỏi chỉ đề cập đến việc ngăn chặn động lượng gốc tự động trong iOS - câu hỏi/giải pháp này liên quan đến việc cho phép di chuyển động lượng trên các div cụ thể trong khi chặn cuộn trên toàn bộ trang . Hữu ích cho các ứng dụng web với nhiều yếu tố vị trí cố định. – 1nfiniti

+0

Nếu bạn muốn tính năng này hoạt động với các phần tử được thêm động (như trong một ứng dụng JS trang đơn), thay thế '$ (". Scrollable "). ('Touchstart', ...)' for '$ (document.body) .on ('touchstart', '.scrollable', ...) '. – micho

Trả lời

11

Mặc dù bạn không chạm mép của div của bạn nội dung, bạn cần cho phép sự kiện touchmove gốc hoạt động trên phần tử đó (để nó có thể cuộn), nhưng bạn sẽ muốn dừng sự kiện từ sủi bọt lên DOM để nó không kích hoạt cuộn trên thân trang.

Khi bạn nhấn ranh giới của phần tử, bạn cần ngăn động lượng gốc tự cuộn hoàn toàn.

Mã tôi sử dụng cho điều này như sau (lời xin lỗi đối với tác giả gốc, điều này được điều chỉnh từ hướng dẫn về chủ đề này tôi tìm thấy ở đâu đó trên internet trong quá khứ ... Dường như không tìm thấy URL bây giờ mặc dù):

nơi elem là DOM của bạn nút

elem.addEventListener('touchstart', function(event){ 
    this.allowUp = (this.scrollTop > 0); 
    this.allowDown = (this.scrollTop < this.scrollHeight - this.clientHeight); 
    this.prevTop = null; this.prevBot = null; 
    this.lastY = event.pageY; 
}); 

elem.addEventListener('touchmove', function(event){ 
    var up = (event.pageY > this.lastY), down = !up; 
    this.lastY = event.pageY; 

    if ((up && this.allowUp) || (down && this.allowDown)) event.stopPropagation(); 
    else event.preventDefault(); 
}); 

tôi thường xác định một loạt các yếu tố và vòng qua chúng - áp dụng mã này vào mỗi một lặp đi lặp lại.

Chúc bạn may mắn, hy vọng điều này sẽ hữu ích.

+0

Tôi cũng giả sử lớp .scrollable của bạn sử dụng '-webkit-overflow-scrolling: touch'? Nếu không, nó sẽ :) – 1nfiniti

+1

Đối với bất kỳ ai bị nhầm lẫn bởi định dạng: áp phích gốc đã thêm phần "Giải pháp" có mã này và triển khai. Nó hoạt động tốt cho tôi. – micho

+0

Nếu bạn đang sử dụng ứng dụng này cho một ứng dụng động, hãy nhớ liên kết lại trình xử lý sự kiện với các phần tử mới khi chúng được thay thế! Tôi thay thế 'elem.addEventListener' cho jQuery '$ (document.body) .on (" touchstart "," .scrollable ", function() {...});' – micho

18

Những câu trả lời ban đầu là tuyệt vời, nhưng có một vài sai sót mà tôi giải quyết:

  • Nếu một phần tử là ở phía trên hoặc phía dưới, nó sẽ không di chuyển lên và xuống tương ứng.
  • Nếu phần tử được thêm động, nó sẽ không có trình xử lý cuộn.
  • Có biến không sử dụng (prevTop, prevBot)

câu trả lời của tôi đề cập đến những. (Chú ý rằng tôi sử dụng .scroll-y, thay vì .scrollable)

Đầu tiên, thêm những quy tắc CSS:

.scroll-y { 
    overflow-y: auto; 
    overflow-x: hidden; 
    -webkit-overflow-scrolling: touch; /* nice webkit native scroll */ 
} 

Thêm lớp .scroll-y đến bất kỳ yếu tố mà bạn muốn thực hiện di chuyển.

Sau đó, thêm này JS ở đâu đó:

// Disable scroll for the document, we'll handle it ourselves 
$(document).on('touchmove', function(e) { 
    e.preventDefault(); 
}); 

// Check if we should allow scrolling up or down 
$(document.body).on("touchstart", ".scroll-y", function (e) { 
    // If the element is scrollable (content overflows), then... 
    if (this.scrollHeight !== this.clientHeight) { 
    // If we're at the top, scroll down one pixel to allow scrolling up 
    if (this.scrollTop === 0) { 
     this.scrollTop = 1; 
    } 
    // If we're at the bottom, scroll up one pixel to allow scrolling down 
    if (this.scrollTop === this.scrollHeight - this.clientHeight) { 
     this.scrollTop = this.scrollHeight - this.clientHeight - 1; 
    } 
    } 
    // Check if we can scroll 
    this.allowUp = this.scrollTop > 0; 
    this.allowDown = this.scrollTop < (this.scrollHeight - this.clientHeight); 
    this.lastY = e.originalEvent.pageY; 
}); 

$(document.body).on('touchmove', ".scroll-y", function(e) { 
    var event = e.originalEvent; 
    var up = event.pageY > this.lastY; 
    var down = !up; 
    this.lastY = event.pageY; 

    if ((up && this.allowUp) || (down && this.allowDown)) { 
    event.stopPropagation(); 
    } else { 
    event.preventDefault(); 
    } 
}); 
+0

Đây là một trong đó làm việc cho tôi, cảm ơn @micho! – matthewpavkov

+1

Tôi ước mình có thể nâng cao điều này thêm một triệu lần nữa, tôi đã tìm kiếm giải pháp làm việc cho điều này trong nhiều ngày, vì vậy cảm ơn! –

0

Tôi tin bouncefix.js là một giải pháp thả-in cho vấn đề này.

0

Ghi chú do Aaron Gray cung cấp đã giúp!

Xem link: http://blog.christoffer.me/six-things-i-learnt-about-ios-safaris-rubber-band-scrolling/

<!doctype html> 
<html lang="en"> 
<head> 
    <meta charset="utf-8"> 
    <meta name="viewport" content="minimum-scale=1.0, width=device-width, maximum-scale=1.0, user-scalable=no, initial-scale=1"> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
    <style> 

     .page{ 
      font-size: 24px; 
      overflow: scroll; 
     } 

     .menu{ 
      position: fixed; 
      top: 0; 
      bottom: 0; 
      left: 0; 
      width: 80%; 
      background: gray; 
      z-index: 1; 
      font-size: 10px; 
      overflow: scroll; 
      /* uncomment to get smooth momentum scroll, but also a rubber band effect */ 
      /*-webkit-overflow-scrolling: touch;*/ 
     } 

     .menu-item{ 
      padding: 10px; 
      background: darkgray; 
      font-size: 24px; 
     } 

    </style> 
</head> 

<body> 

<div class="menu scrollable"> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
    <div class="menu-item">hello world</div> 
</div> 

<div class="page disable-scrolling"> 
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's 
    standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make 
    a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, 
    remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing 
    Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions 
    of Lorem Ipsum. 
</div> 

<script> 


    document.ontouchmove = function (event) { 

     var isTouchMoveAllowed = true, target = event.target; 

     while (target !== null) { 
      if (target.classList && target.classList.contains('disable-scrolling')) { 
       isTouchMoveAllowed = false; 
       break; 
      } 
      target = target.parentNode; 
     } 

     if (!isTouchMoveAllowed) { 
      event.preventDefault(); 
     } 

    }; 

    function removeIOSRubberEffect(element) { 

     element.addEventListener("touchstart", function() { 

      var top = element.scrollTop, totalScroll = element.scrollHeight, currentScroll = top + element.offsetHeight; 

      if (top === 0) { 
       element.scrollTop = 1; 
      } else if (currentScroll === totalScroll) { 
       element.scrollTop = top - 1; 
      } 

     }); 

    } 

    removeIOSRubberEffect(document.querySelector(".scrollable")); 


</script> 

</body> 
</html> 
Các vấn đề liên quan