ipad safari: vô hiệu hóa cuộn, và hiệu ứng thoát?


126

Tôi đang làm việc trên một ứng dụng dựa trên trình duyệt, hiện tôi đang phát triển và tạo kiểu cho trình duyệt ipad safari.

Tôi đang tìm kiếm hai thứ trên ipad: Làm cách nào tôi có thể tắt cuộn dọc cho các trang không yêu cầu? & làm thế nào tôi có thể vô hiệu hóa hiệu ứng nảy đàn hồi?


chỉ tham khảo câu trả lời sau đây chỉ có một câu trả lời cho tôi và hiện tại ( stackoverflow.com/a/51176339/1979180 )
frage

Câu trả lời:


157

Câu trả lời này không còn được áp dụng, trừ khi bạn đang phát triển cho một thiết bị iOS rất cũ ... Vui lòng xem các giải pháp khác


Câu trả lời năm 2011: Đối với một ứng dụng web / html chạy trong iOS Safari, bạn muốn một cái gì đó như

document.ontouchmove = function(event){
    event.preventDefault();
}

Đối với iOS 5, bạn có thể muốn đưa vào tài khoản sau: document.ontouchmove và cuộn trên iOS 5

Cập nhật tháng 9 năm 2014: Một cách tiếp cận kỹ lưỡng hơn có thể được tìm thấy ở đây: https://github.com/luster-io/prevent-overscroll . Để biết điều đó và rất nhiều lời khuyên về ứng dụng web hữu ích, hãy xem http://www.luster.io/blog/9-29-14-mobile-web-checklist.html

Cập nhật tháng 3 năm 2016: Liên kết cuối cùng đó không còn hoạt động - xem https://web.archive.org/web/20151103001838/http://www.luster.io/blog/9-29-14-mobile-web-checklist .html cho phiên bản lưu trữ thay thế. Cảm ơn @falsarella đã chỉ ra điều đó.


1
Tôi có ứng dụng web chạy trong iOS Safari và tôi đã thử vô hiệu hóa sự kiện ontouchmove nhưng vẫn có thể thấy hiệu ứng thoát nếu được thực hiện cẩn thận. (iOS 5)
Nilesh

7
Còn việc vô hiệu hóa hiệu ứng thoát ... thì sao?
Yuval A.

6
Vấn đề với cách tiếp cận này là, các div có thể cuộn trong dom của bạn sẽ không cuộn nữa. Tùy thuộc vào thiết lập dom của bạn, có nhiều cách xung quanh này.
huesforalice

3
Có một nhóm người ở đây hỏi về việc di chuyển các div trong khi sử dụng điều này vì vậy .. để làm cho các div đó có thể cuộn được, hãy thêm onTouchMove: function(e) { e.stopPropagation(); e.stopImmediatePropagation(); } Nó sẽ ngăn sự kiện đánh vào cơ thể, nhưng cơ thể sẽ vẫn không bị nảy. Chỉnh sửa: Đây là giả sử bạn đặt $ ('div'). On ('touchmove', ... onTouchMove);
Matt Kenefick

1
@OskarAustegard Các liên kết cuối cùng đã không làm việc cho tôi, nhưng tôi có thể tìm thấy những nội dung về lưu trữ web: web.archive.org/web/20151103001838/http://www.luster.io/blog/...
falsarella

116

Bạn cũng có thể thay đổi vị trí của phần thân / html thành cố định:

body,
html {
  position: fixed;
}

2
Điều này thực sự hoạt động rất tốt trên iPad iOS 8.2 Safari; không có hiệu ứng nảy nữa.
Akseli Palén

3
Cách tốt nhất để làm điều đó tôi đã thấy cho đến nay
hildende

8
Không hoạt động nếu bạn muốn đặt một cái gì đó có vị trí: tuyệt đối và tất cả các mặt được đặt thành 0 (để tạo một div toàn màn hình) - toàn bộ tài liệu của bạn co lại thành không có gì.
RIV

4
Trang nhảy trở lại đầu trang cho tôi khi tôi sử dụng trang này và sau đó tôi tập trung vào một đầu vào. Bạn có biết một cách xung quanh này?
Julie

1
@riv thêm chiều rộng: 100%; Chiều cao: 100% cho cả cơ thể và html đã giúp tôi.
Tim

57

Để ngăn cuộn trên các trình duyệt di động hiện đại, bạn cần thêm thụ động: false. Tôi đã kéo tóc ra để làm việc này cho đến khi tôi tìm thấy giải pháp này. Tôi chỉ tìm thấy điều này được đề cập ở một nơi khác trên internet.

function preventDefault(e){
    e.preventDefault();
}

function disableScroll(){
    document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll(){
    document.body.removeEventListener('touchmove', preventDefault);
}


7
Nếu không có { passive: false }nó chắc chắn không hoạt động !!! Chào mừng bạn đến với anh chàng StackOverflow
Ser

2
Tôi đánh giá cao bạn đã cung cấp giải pháp này!
Paul Z.

6
Đây là câu trả lời chính xác. Bạn có thể xem giải thích tại đây: developer.mozilla.org/en-US/docs/Web/API/EventTarget/, sau khi Chrome 54 touchmove mặc định bị động thành đúng, điều đó có nghĩa là các cuộc gọi của DefDefault sẽ bị bỏ qua. Đó là lý do tại sao bạn phải vượt qua {thụ động: sai}, vì vậy, lệnh gọi DefDefault không bị bỏ qua.
derickito

1
Bạn đang khai báo hàm trong JS - Nhưng làm thế nào để bạn gọi hàm này trên một phần tử để nó hoạt động như được đề xuất?
ikwyl6

4
Điều này hoạt động tuyệt vời nếu bạn muốn vô hiệu hóa tất cả các loại cuộn. Nhưng nếu tôi chỉ muốn vô hiệu hóa cuộn trên cơ thể và giữ khả năng cuộn trên một phần tử overflow-y: scrollthì sao? Ví dụ: có một phương thức có chiều cao xem cao hơn cơ thể.
Calsal

7

Bạn có thể sử dụng đoạn mã jQuery này để làm điều này:

$(document).bind(
      'touchmove',
          function(e) {
            e.preventDefault();
          }
);

Điều này sẽ chặn cuộn dọc và bất kỳ hiệu ứng bật lại nào xảy ra trên các trang của bạn.


11
Đây không phải là Javascript, đó là jQuery. Bạn nên đề cập rằng, không phải tất cả mọi người đang sử dụng khuôn khổ đó.
inta

Làm thế nào tôi có thể dừng nảy hoặc cuộn ngang
fidel castro

Cuộn ngang bạn thậm chí có thể vô hiệu hóa nó chỉ bằng css, áp dụng overflow-x: hidden; đến container chính của bạn. Tôi nhận thấy trong các phiên bản mới nhất của safari, bạn không thể vô hiệu hóa hiệu ứng thoát. Đây là một tính năng gốc của trình duyệt trên thiết bị di động.
Alessandro Incarnati

6
@inta Chỉ cần nói điều này thực sự là javascript. Nó chỉ không phải là javascript thuần túy.
Ben Lorantfy

6
overflow: scroll;
-webkit-overflow-scrolling: touch;

Trên container, bạn có thể đặt hiệu ứng thoát bên trong phần tử

Nguồn: http://www.kylejlarson.com/blog/2011/fixed-elements-and-scrolling-divs-in-ios-5/


1
Cùng với overflow:hiddentrên <body>, đây vẫn là giải pháp tốt nhất. Tuy nhiên, khi mở bàn phím hoặc trượt trên đáy màn hình, nó sẽ không hoạt động nữa.
Fabian von Ellerts

thử nhập vào tiêu điểm loại bỏ tràn
user956584

4

Tôi biết điều này hơi khó hiểu nhưng tôi đã sử dụng Swiffy để chuyển đổi Flash thành một trò chơi HTML5 tương tác và gặp phải vấn đề cuộn tương tự nhưng không tìm thấy giải pháp nào hiệu quả.

Vấn đề tôi gặp phải là sân khấu Swiffy chiếm toàn bộ màn hình, vì vậy ngay khi tải xong, sự kiện touchmove tài liệu không bao giờ được kích hoạt.

Nếu tôi cố gắng thêm sự kiện tương tự vào thùng chứa Swiffy, nó sẽ được thay thế ngay khi sân khấu được tải.

Cuối cùng, tôi đã giải quyết nó (khá lộn xộn) bằng cách áp dụng sự kiện touchmove cho mọi DIV trong sân khấu. Vì những div này cũng luôn thay đổi, tôi cần tiếp tục kiểm tra chúng.

Đây là giải pháp của tôi, có vẻ như hoạt động tốt. Tôi hy vọng nó hữu ích cho bất cứ ai khác đang cố gắng tìm giải pháp tương tự như tôi.

var divInterval = setInterval(updateDivs,50);
function updateDivs(){
$("#swiffycontainer > div").bind(
    'touchmove',
     function(e) {
        e.preventDefault();
    }
);}

điều này vô hiệu hóa toàn bộ cuộn trong ipad
fidel castro

3

Mã để loại bỏ ipad safari: vô hiệu hóa cuộn và hiệu ứng thoát

   document.addEventListener("touchmove", function (e) {
        e.preventDefault();
    }, { passive: false });

Nếu bạn có thẻ canvas bên trong tài liệu, đôi khi nó sẽ ảnh hưởng đến khả năng sử dụng của đối tượng bên trong Canvas (ví dụ: chuyển động của đối tượng); Vì vậy, thêm mã dưới đây để sửa nó.

    document.getElementById("canvasId").addEventListener("touchmove", function (e) {
        e.stopPropagation();
    }, { passive: false });

2

Hãy thử sollutuion JS này :

var xStart, yStart = 0; 

document.addEventListener('touchstart', function(e) {
    xStart = e.touches[0].screenX;
    yStart = e.touches[0].screenY;
}); 

document.addEventListener('touchmove', function(e) {
    var xMovement = Math.abs(e.touches[0].screenX - xStart);
    var yMovement = Math.abs(e.touches[0].screenY - yStart);
    if((yMovement * 3) > xMovement) {
        e.preventDefault();
    }
});

Ngăn chặn các thao tác cuộn và nảy mặc định của Safari mà không tách rời trình nghe sự kiện chạm của bạn.


Điều này ngăn ứng dụng web cuộn hoàn toàn trên phần tử cơ thể.
MartijnICU

2

không có giải pháp nào phù hợp với tôi Đây là cách tôi làm điều đó.

  html,body {
      position: fixed;
      overflow: hidden;
    }
  .the_element_that_you_want_to_have_scrolling{
      -webkit-overflow-scrolling: touch;
  }

Tôi sẽ làm .the_element_that_you_want_to_have_scrolling {scrolling: touch; }
Roy Segall

Câu trả lời của bạn đã làm việc cho tôi về html, nhưng tôi không thể lấy "the_element_that_you_want_to_have_scrolling" để cuộn. Yếu tố này được lồng bên trong một vài div nằm dưới cơ thể. Có vấn đề gì với bất kỳ thẻ yếu tố điển hình nào đối với div lồng nhau này mà tôi muốn có nó cuộn không? Tôi có vị trí: tương đối.
ikwyl6


1

Đối với những người đang sử dụng MyScript, Ứng dụng web và đang vật lộn với thao tác cuộn / kéo cơ thể (trên iPad và Máy tính bảng) thay vì thực sự viết:

<body touch-action="none" unresolved>

Điều đó đã sửa nó cho tôi.


1

Bạn có thể sử dụng js để ngăn cuộn:

let body = document.body;

let hideScroll = function(e) {
  e.preventDefault();
};

function toggleScroll (bool) {

  if (bool === true) {
    body.addEventListener("touchmove", hideScroll);
  } else {
    body.removeEventListener("touchmove", hideScroll);
  }
}

Và hơn là chỉ chạy / dừng toggleScrollfunc khi bạn opnen / đóng phương thức.

Như thế này toggleScroll(true) / toggleScroll(false)

(Điều này chỉ dành cho iOS, trên Android không hoạt động)


1

Hãy thử giải pháp JS này để bật webkitOverflowScrollingphong cách. Thủ thuật ở đây là phong cách này bị tắt, Safari di động chuyển sang cuộn thông thường và ngăn chặn quá nảy - than ôi, nó không thể hủy kéo liên tục. Giải pháp phức tạp này cũng theo dõi onscrollkhi độ nảy trên đỉnh tạo ra scrollTopâm tính có thể được theo dõi. Giải pháp này đã được thử nghiệm trên iOS 12.1.1 và có một nhược điểm duy nhất: trong khi việc tăng tốc cuộn quá mức vẫn xảy ra do việc đặt lại kiểu có thể không hủy được ngay lập tức.

function preventScrollVerticalBounceEffect(container) {
  setTouchScroll(true) //!: enable before the first scroll attempt

  container.addEventListener("touchstart", onTouchStart)
  container.addEventListener("touchmove", onTouch, { passive: false })
  container.addEventListener("touchend", onTouchEnd)
  container.addEventListener("scroll", onScroll)

  function isTouchScroll() {
    return !!container.style.webkitOverflowScrolling
  }

  let prevScrollTop = 0, prevTouchY, opid = 0

  function setTouchScroll(on) {
    container.style.webkitOverflowScrolling = on ? "touch" : null

    //Hint: auto-enabling after a small pause makes the start
    // smoothly accelerated as required. After the pause the
    // scroll position is settled, and there is no delta to
    // make over-bounce by dragging the finger. But still,
    // accelerated content makes short single over-bounce
    // as acceleration may not be off instantly.

    const xopid = ++opid
    !on && setTimeout(() => (xopid === opid) && setTouchScroll(true), 250)

    if(!on && container.scrollTop < 16)
      container.scrollTop = 0
    prevScrollTop = container.scrollTop
  }

  function isBounceOverTop() {
    const dY = container.scrollTop - prevScrollTop
    return dY < 0 && container.scrollTop < 16
  }

  function isBounceOverBottom(touchY) {
    const dY = touchY - prevTouchY

    //Hint: trying to bounce over the bottom, the finger moves
    // up the screen, thus Y becomes smaller. We prevent this.

    return dY < 0 && container.scrollHeight - 16 <=
      container.scrollTop + container.offsetHeight
  }

  function onTouchStart(e) {
    prevTouchY = e.touches[0].pageY
  }

  function onTouch(e) {
    const touchY = e.touches[0].pageY

    if(isBounceOverBottom(touchY)) {
      if(isTouchScroll())
        setTouchScroll(false)
      e.preventDefault()
    }

    prevTouchY = touchY
  }

  function onTouchEnd() {
    prevTouchY = undefined
  }

  function onScroll() {
    if(isTouchScroll() && isBounceOverTop()) {
      setTouchScroll(false)
    }
  }
}

1

câu trả lời được cải thiện @Ben Bos và nhận xét của @Tim

Css này sẽ giúp ngăn vấn đề cuộn và hiệu năng với kết xuất lại css vì vị trí thay đổi / độ trễ nhỏ mà không có chiều rộng và chiều cao

body,
html {
  position: fixed;
  width: 100%; 
  height: 100%
}


Trên iOS13, đây là giải pháp sạch nhất đối với tôi và chưa tìm thấy bất kỳ nhược điểm nào ...
Soylent Graham

0

Đối với những người bạn không muốn thoát khỏi việc nảy nhưng chỉ cần biết khi nào nó dừng (ví dụ: để bắt đầu một số tính toán khoảng cách màn hình), bạn có thể thực hiện các thao tác sau (container là phần tử container tràn):

    const isBouncing = this.container.scrollTop < 0 ||
    this.container.scrollTop + this.container.offsetHeight >
        this.container.scrollHeight

0

Vô hiệu hóa hiệu ứng cuộn nảy safari:

html,
body {
  height: 100%;
  width: 100%;
  overflow: auto;
  position: fixed;
}  

-1

Tương tự như kiwi tức giận, tôi đã làm cho nó hoạt động bằng cách sử dụng chiều cao thay vì vị trí:

html,body {
  height: 100%;
  overflow: hidden;
}

.the_element_that_you_want_to_have_scrolling{
  -webkit-overflow-scrolling: touch;
}

vì tài liệu này sẽ cho phép bật lại sau khi đà không bị vô hiệu hóa
CaSUaL

@CaSUaL Không chắc ý bạn là gì? Giải pháp này hiệu quả với trường hợp sử dụng của tôi ...
austinh7

-1

Đã thử nghiệm giải pháp, hoạt động trên iOS 12.x

Đây là vấn đề tôi gặp phải:

<body> <!-- the whole body can be scroll vertically -->
  <article>

    <my_gallery> <!-- some picture gallery, can be scroll horizontally -->
    </my_gallery>

  </article>
</body>

Trong khi tôi cuộn bộ sưu tập của mình, cơ thể luôn tự cuộn (vuốt người không thực sự nằm ngang), điều đó làm cho bộ sưu tập của tôi trở nên vô dụng.

Đây là những gì tôi đã làm trong khi bộ sưu tập của tôi bắt đầu cuộn

var html=jQuery('html');
html.css('overflow-y', 'hidden');
//above code works on mobile Chrome/Edge/Firefox
document.ontouchmove=function(e){e.preventDefault();} //Add this only for mobile Safari

Và khi bộ sưu tập của tôi kết thúc việc cuộn ...

var html=jQuery('html');
html.css('overflow-y', 'scroll');
document.ontouchmove=function(e){return true;}

Hy vọng điều này sẽ giúp ~

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.