2013-06-03 10 views
10

Unter Mobile Safari, ist es möglich, eine absolut positionierte div zu scrollen, ohne die gesamte Seite auf und ab wippen, wenn es die Schriftrolle an den Rändern (elastisch Scrollen)?verhindern ganze Seite scrollen iOS

ist hier ein minimales Arbeitsbeispiel der Frage, die ich bin vor:

<!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> 

Lösung:

$(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

nein, kein Duplikat. mit zwei 'div's Änderungen. –

+2

Leute, die dies als Duplikat markieren - Dies ist keine doppelte Frage - die referenzierte Frage behandelt nur das Verhindern des nativen Impuls Scrollens in iOS - diese Frage/Lösung besteht darin, das Scrollen von bestimmten divs zu aktivieren, während das Scrollen auf der gesamten Seite blockiert wird . Nützlich für Web-Apps mit vielen festen Positionselementen. – 1nfiniti

+0

Wenn Sie möchten, dass dies mit dynamisch hinzugefügten Elementen funktioniert (wie in einer JS-App mit einer einzelnen Seite), ersetzen Sie '$ (". Scrollable "). On ('touchstart', ...)' für '$ (document.body) .on ('touchstart', '.scrollable', ...) '. – micho

Antwort

11

Während Sie nicht die Ränder der divs schlagen Inhalt, Sie müssen das native touchmove-Ereignis an diesem Element arbeiten lassen (damit es scrollen kann), aber Sie werden wollen das Ereignis zu stoppen aus dem DOM sprudelnd, so dass es nicht auf dem Seitentext Scrollen auslöst.

Wenn Sie die Grenze Ihres Elements treffen, müssen Sie verhindern, dass das ursprüngliche Momentum vollständig durchläuft.

Der Code, den ich dafür verwende, ist wie folgt (Entschuldigung für den ursprünglichen Autor, dies ist aus einem Tutorial zu diesem Thema ich irgendwo im Internet in der Vergangenheit gefunden ... scheint nicht die URL zu finden jetzt aber):

wo Elem Ihres DOM Knotens

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

I in die Regel eine Reihe von Elementen und eine Schleife durch sie definieren, - der Code zu jedem iterativen Anwendung.

Viel Glück, hoffe das hilft.

+0

Ich nehme auch an, dass Ihre .scrollable-Klasse '-webkit-overflow-scrolling: touch' verwendet? Wenn nicht, sollte es :) – 1nfiniti

+1

Für wer durch das Format verwirrt ist: das ursprüngliche Plakat fügte einen "Lösungs" Teil hinzu, der diesen Code nimmt und es implementiert. Es funktioniert gut für mich. – micho

+0

Wenn Sie dies für eine dynamische Anwendung verwenden, denken Sie daran, die Ereignislistener beim Ersetzen an die neuen Elemente erneut zu binden. Ich ersetzte "elem.addEventListener" für jQuery 's (document.body) .on (" touchstart "," .scrollable ", function() {...});' – micho

18

Die ursprünglichen Antworten sind fantastisch, aber haben ein paar Fehler, die ich gelöst:

  • Wenn ein Element am oberen oder unteren Rand ist, wird es nicht nach oben bzw. nach unten.
  • Wenn ein Element dynamisch hinzugefügt wird, verfügt es nicht über die Scroll-Handler.
  • Es gab nicht verwendeten Variablen (prevTop, prevBot)

Meine Antwort richtet sich an. (Beachten Sie, dass ich .scroll-y verwenden, statt .scrollable)

Zuerst fügen diese CSS-Regeln:

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

Fügen Sie die .scroll-y Klasse auf alle Elemente, die Sie blättern machen wollen.

Dann fügen Sie diese irgendwo JS:

// 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

Dies ist die eine, die für mich arbeitete, danke @micho! – matthewpavkov

+1

Ich wünschte, ich könnte das noch millionenfach verbessern, ich habe seit Tagen nach einer funktionierenden Lösung gesucht, also danke! –

0

Ich glaube bouncefix.js ist ein Drop-in-Lösung für dieses Problem.

0

Die Notiz von Aaron Grey geholfen!

Siehe 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>