jquery - qué - iphone actualizacion en segundo plano whatsapp
¿Cómo deshabilitar la goma en las aplicaciones web de iOS? (7)
Esta:
$(''body'').on(''touchmove'', function(e) { e.preventDefault(); });
Funciona, pero deshabilitará el desplazamiento en toda la página, lo que dista mucho de ser ideal.
Esta:
$(''*'').on(''touchstart'', function(e){
var element = $(this).get(0);
if ( element.scrollTop <= 0 ) element.scrollTop = 1;
if ( element.scrollTop + element.offsetHeight >= element.scrollHeight ) element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
});
Funciona en páginas que tienen un área de desplazamiento. Sin embargo, cuando no haya nada para desplazarse, volverá a mostrar la banda elástica.
Así que mi pregunta:
¿Cómo se puede deshabilitar el efecto de la banda elástica y aún mantener las áreas de desplazamiento de -webkit-overflow-scrolling
?
[Actualizar]
Mejor solución
Deshabilite el desplazamiento en todos los elementos no desplazables, como una barra de pestañas o una barra de navegación.
anElement.addEventListener(''touchmove'', function( event ){ event.preventDefault() };
Adjunte un controlador de desplazamiento a los elementos desplazables, como el contenido principal.
anElement.addEventListener(''touchstart'', function( event ){
if( this.scrollTop === 0 ) {
this.scrollTop += 1;
} else if( this.scrollTop + this.offsetHeight >= this.scrollHeight ) {
this.scrollTop -= 1;
}
}
Aquí hay una solución que usa jQuery y Hammer.js (implementación de jquery). Son dos bibliotecas, pero si estás trabajando en dispositivos móviles, es probable que quieras incluir Hammer de todos modos.
Para cada evento de arrastre que burbujea hasta la parte superior (por lo tanto, las interacciones de arrastre sin desplazamiento pueden usar stopPropagation) el controlador comprueba si burbujea a través de algún elemento con clase = desplazamiento, si es así, si el usuario está desplazándose dentro de los límites permitidos scrollContainer y solo entonces permite el desplazamiento nativo.
$("body").hammer().on(''drag swipe'', function(e){
var scrollTarget = $(e.gesture.target).closest(".scrollable");
if(scrollTarget.length)
{
var scrollTopMax = scrollTarget[0].scrollHeight - scrollTarget.outerHeight();
if(scrollTopMax > 0){
var scrollTop = scrollTarget.scrollTop();
if(scrollTop > 0 && scrollTop < scrollTopMax){
//console.log("scrolling in the middle");
}
else if(scrollTop <= 0 && e.gesture.deltaY < 0){
//console.log("scrolling from top");
}
else if(scrollTop >= scrollTopMax && e.gesture.deltaY > 0){
//console.log("scrolling from bottom");
}
else{
//console.log("trying to scroll out of boundaries");
e.gesture.preventDefault();
}
}
else{
//console.log("content to short to scroll");
e.gesture.preventDefault();
}
}
else{
//console.log("no containing element with class=scrollable");
e.gesture.preventDefault();
}
});
Para matar arrastres a través de pellizco, etc; escape como sea necesario para permitir el zoom si su vista es escalable por el usuario
$("body").hammer().on(''doubletap rotate pinch'', function(e){
e.gesture.preventDefault();
});
Probado en ios7 / safari, android4.3 / webview y android4.3 / firefoxMobile25 y la única solución que no se rompió.
Basándonos en la respuesta de @ Mark, se nos ocurrió esta alternativa, que parece funcionar. Reemplace .page_list
con los nombres de clase de los elementos desplazables.
var INITIAL_Y = 0; // Tracks initial Y position, needed to kill Safari bounce effect
function kill_safari_bounce() {
$( document ).on( ''touchstart'', function( e ){
INITIAL_Y = e.originalEvent.touches[0].clientY;
});
$( document ).on( ''touchmove'', function( e ) {
// Get scrollable ancestor if one exists
var scrollable_ancestor = $( e.target ).closest( ''.page_list'' )[0];
// Nothing scrollable? Block move.
if ( !scrollable_ancestor ) {
e.preventDefault();
return;
}
// If here, prevent move if at scrollable boundaries.
var scroll_delta = INITIAL_Y - e.originalEvent.touches[0].clientY;
var scroll_pos = scrollable_ancestor.scrollTop;
var at_bottom = (scroll_pos + $(scrollable_ancestor).height()) == scrollable_ancestor.scrollHeight;
if ( (scroll_delta < 0 && scroll_pos == 0) ||
(scroll_delta > 0 && at_bottom) ){
e.preventDefault();
}
});
}
Desafortunadamente, no hay una solución para esto, ya que el desplazamiento de la banda elástica en Mobile Safari es una "característica" incorporada del navegador en sí. Al utilizar cualquier mecanismo de desplazamiento predeterminado provisto por el navegador, terminará con el desplazamiento de la banda elástica hasta cierto punto.
Hay dos maneras en que sugeriría abordar esto:
Método 1
touchmove
evento touchmove
en el elemento </body>
y verifique el destino del evento touchmove
para ver si desea que se dispare o no, así:
HTML
<div class="scroll">
<p>...</p>
<p>...</p>
</div>
JS
$(''body'').on(''touchmove'', function(e) {
// this is the node the touchmove event fired on
// in this example it would be the </p> element
target = e.target;
// we need to find the parent container
// we get it like so; assumes div as parent
parent = $(e.target).closest(''div'');
// check if the parent is a scroll window by class //
if ($(parent).hasClass(''scroll'')){
// ignore as we want the scroll to happen
} else {
e.preventDefault();
}
});
Este método utiliza el desplazamiento predeterminado del navegador, sin embargo, tiene el inconveniente de que todavía tendrá el desplazamiento de la banda elástica en la parte superior o inferior del desplazamiento </div>
.
Método 2
touchmove
evento touchmove
del elemento </body>
como antes, sin embargo, en este caso, evitamos todos los eventos touchmove
y confiamos en el excelente complemento iScroll 4 para manejar el desplazamiento, así:
HTML
<div id="wrapper">
<div id="scroller">
<p>...</p>
<p>...</p>
</div>
</div>
JS
$(document).ready(function(){
// prevent all scroll //
$(''body'').on(''touchmove'', function(e) {
e.preventDefault();
});
// apply iscroll to scrolling element
// requires use of id
var newscroll = new iScroll(''wrapper'');
});
Este es mi método preferido, ya que bloquea todo el desplazamiento de la banda de goma y proporciona un área de desplazamiento agradable, sin embargo, se basa en el uso de un complemento.
espero que esto ayude
Escribí, en mi opinión, la mejor solución para este problema. Deshabilitará el desplazamiento en general a menos que el elemento tenga y desplazamiento.
/********************************************************************************
* Disable rubber band (c)2013 - Mark van Wijnen | www.CrystalMinds.nl
********************************************************************************/
$(function(){
var scrollY = 0;
$(document).on(''touchstart'', function( e ){
scrollY = e.originalEvent.touches.item(0).clientY;
});
$(document).on(''touchmove'', function( e ){
var scrollPos = e.target.scrollTop;
var scrollDelta = scrollY - e.originalEvent.touches.item(0).clientY;
var scrollBottom = scrollPos + $(e.target).height();
scrollY = e.originalEvent.touches.item(0).clientY;
if ( $(e.target).css( ''overflow-y'' ) != ''scroll'' || ( scrollDelta < 0 && scrollPos == 0 ) || ( scrollDelta > 0 && scrollBottom == e.target.scrollHeight ) )
e.preventDefault();
});
});
Finalmente mezclé algunos métodos y estos códigos son la versión de trabajo. Pero debes incluir el hammer.js
CSS
.scrollable{
overflow:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;
*{-webkit-transform:translate3d(0,0,0);}
}
JAVASCRIPT
$(document).on("touchmove",function(e){
e.preventDefault();
});
$("body").on("touchstart",".scrollable",function(e){
if(e.currentTarget.scrollTop===0){
e.currentTarget.scrollTop = 1;
}else if(e.currentTarget.scrollHeight === e.currentTarget.scrollTop + e.currentTarget.offsetHeight){
e.currentTarget.scrollTop-=1;
}
});
$("body").on("touchmove",".scrollable",function(e){
e.stopPropagation();
});
$("body").hammer().on("pinch",function(e){
e.gesture.preventDefault();
});
Me encontré con el mismo problema recientemente con un SPA donde la banda de goma <body>
estaba restando valor a la experiencia, pero necesitaba desplazarme en subáreas. Muchas gracias a las sugerencias de dSquared, ya que el Método 1 funcionó mejor para mí. Aquí está mi pequeña expansión de su sugerencia que implementé en un proyecto de trabajo que busca todo el camino hacia el árbol para encontrar cualquier elemento (no solo divs) que tenga una clase .scroll
:
// Prevent rubber-banding of the body, but allow for scrolling elements
$(''body'').on(''touchmove'', function (e) {
var searchTerms = ''.scroll, .scroll-y, .scroll-x'',
$target = $(e.target),
parents = $target.parents(searchTerms);
if (parents.length || $target.hasClass(searchTerms)) {
// ignore as we want the scroll to happen
// (This is where we may need to check if at limit)
} else {
e.preventDefault();
}
});
Y aquí está el aspecto del CSS:
body {
height: 100%;
overflow: hidden;
}
.scroll, .scroll-y, .scroll-x {
-webkit-overflow-scrolling: touch;
}
.scroll > *, .scroll-y > *, .scroll-x > * {
-webkit-transform : translateZ(0);
}
.scroll { overflow: auto; }
.scroll-y { overflow-y: auto; }
.scroll-x { overflow-x: auto; }
Solo necesita una biblioteca (jQuery o Zepto ) y obtiene un desplazamiento nativo con impulso y sin bandas de goma en el cuerpo. Además, he agregado el translateZ para solucionar algunos problemas que he tenido con los elementos que desaparecen durante el desplazamiento y se puede usar para GPU para acelerar sus elementos .
PERO (y esto es un gran pero), como lo señala dSquared, las bandas elásticas de toda la página cuando el elemento de desplazamiento está en su límite e intentaron desplazarse más. Personalmente, considero que esto es un fracaso, así que continúo trabajando en ello, solo quería colaborar para tratar de resolver esto. Agregar una marca a lo largo de las líneas del código del OP podría ser la respuesta, pero no lo he probado.
ACTUALIZACIÓN (10/7/12):
Después de mucho trabajo, conseguí que el siguiente código funcionara perfectamente en iOS6 (no lo he probado en nada más). No hay bandas elásticas en el cuerpo, no hay más problemas cuando se encuentra en el límite del área de desplazamiento y tiene un rendimiento de desplazamiento nativo en todo momento. Obviamente, es mucho más código que originalmente, pero creo que esto dará el comportamiento más cercano a los objetivos del OP.
(function registerScrolling($) {
var prevTouchPosition = {},
scrollYClass = ''scroll-y'',
scrollXClass = ''scroll-x'',
searchTerms = ''.'' + scrollYClass + '', .'' + scrollXClass;
$(''body'').on(''touchstart'', function (e) {
var $scroll = $(e.target).closest(searchTerms),
targetTouch = e.originalEvent.targetTouches[0];
// Store previous touch position if within a scroll element
prevTouchPosition = $scroll.length ? { x: targetTouch.pageX, y: targetTouch.pageY } : {};
});
$(''body'').on(''touchmove'', function (e) {
var $scroll = $(e.target).closest(searchTerms),
targetTouch = e.originalEvent.targetTouches[0];
if (prevTouchPosition && $scroll.length) {
// Set move helper and update previous touch position
var move = {
x: targetTouch.pageX - prevTouchPosition.x,
y: targetTouch.pageY - prevTouchPosition.y
};
prevTouchPosition = { x: targetTouch.pageX, y: targetTouch.pageY };
// Check for scroll-y or scroll-x classes
if ($scroll.hasClass(scrollYClass)) {
var scrollHeight = $scroll[0].scrollHeight,
outerHeight = $scroll.outerHeight(),
atUpperLimit = ($scroll.scrollTop() === 0),
atLowerLimit = (scrollHeight - $scroll.scrollTop() === outerHeight);
if (scrollHeight > outerHeight) {
// If at either limit move 1px away to allow normal scroll behavior on future moves,
// but stop propagation on this move to remove limit behavior bubbling up to body
if (move.y > 0 && atUpperLimit) {
$scroll.scrollTop(1);
e.stopPropagation();
} else if (move.y < 0 && atLowerLimit) {
$scroll.scrollTop($scroll.scrollTop() - 1);
e.stopPropagation();
}
// If only moving right or left, prevent bad scroll.
if(Math.abs(move.x) > 0 && Math.abs(move.y) < 3){
e.preventDefault()
}
// Normal scrolling behavior passes through
} else {
// No scrolling / adjustment when there is nothing to scroll
e.preventDefault();
}
} else if ($scroll.hasClass(scrollXClass)) {
var scrollWidth = $scroll[0].scrollWidth,
outerWidth = $scroll.outerWidth(),
atLeftLimit = $scroll.scrollLeft() === 0,
atRightLimit = scrollWidth - $scroll.scrollLeft() === outerWidth;
if (scrollWidth > outerWidth) {
if (move.x > 0 && atLeftLimit) {
$scroll.scrollLeft(1);
e.stopPropagation();
} else if (move.x < 0 && atRightLimit) {
$scroll.scrollLeft($scroll.scrollLeft() - 1);
e.stopPropagation();
}
// If only moving up or down, prevent bad scroll.
if(Math.abs(move.y) > 0 && Math.abs(move.x) < 3){
e.preventDefault();
}
// Normal scrolling behavior passes through
} else {
// No scrolling / adjustment when there is nothing to scroll
e.preventDefault();
}
}
} else {
// Prevent scrolling on non-scrolling elements
e.preventDefault();
}
});
})(jQuery);
Solo agrega un -webkit-overflow-scrolling: auto;
al div que quieres evitar que rebote