2011-11-08 19 views
9

Estoy creando una aplicación web a pantalla completa que tendrá algunos módulos/widgets que hacen uso del nuevo iOS 5 overflow: funciones de desplazamiento. Lo que quiero es deshabilitar ese efecto 'saltarín' cuando se desplaza el html/body (ya que es una pantalla completa) pero mantener ese efecto solo en los elementos desplazables.deshabilitando el desplazamiento animoso solo para html pero manteniendo para elementos con overflow: scroll

para suavizar los efectos de los elementos desplazables que tengo:

html, body { overflow: hidden; } 

.scrollable { 
    overflow: scroll; 
    -webkit-overflow-scrolling: touch; 
} 

y luego el siguiente script que desactiva el efecto de desplazamiento táctil:

$(document).bind('touchmove', function (e) { 
    if (e.target === document.documentElement) { 
     e.preventDefault(); 
    } 
}); 

aunque esto no parece funcionar en absoluto , porque al desplazar un elemento al extremo inferior o superior también se desplaza al documentElement.

¿Hay alguna forma de desactivar solo ese efecto para el cuerpo del elemento html?

Aquí es un buen ejemplo de cómo esto afecta a la funcionalidad:

http://dl.dropbox.com/u/1928164/ios5/index.html

+0

No creo que su controlador de eventos llegue a prevenirDefault() porque el objetivo es el elemento que desencadenó el evento, que nunca puede ser document.documentElement (). Entonces, estás viendo el mismo comportamiento como si no tuvieras el controlador de eventos. – ThinkingStiff

+0

que sería 'currentTarget', me temo. el objetivo puede devolver cualquier cosa dentro de él, puede intentar;) – zanona

+0

currentTarget devuelve el elemento con el oyente, no el elemento que lanzó el evento. – ThinkingStiff

Respuesta

0

Resulta para mí que la única solución eficaz era utilizar joelambert/ScrollFix guión, funcionó muy bien sin retrasos, de hecho ya lo estoy usando en uno de mis proyectos.

También puede consultar sobre este tema en más detalles en his blog post. Lo siento por los otros usuarios que respondieron pero realmente no obtuve esas respuestas que funcionen para mí.

2

Es desafortunado que -webkit-overflow-scrolling no maneja esto mejor. Debe hacer un seguimiento de la posición y para que funcione. Puse la clase scroll en cualquier elemento que quiera desplazar en mi página, como <ul> elementos. Envuelva un <div> alrededor del <ul> que llena la ventana gráfica con overflow-y: auto. No ponga overflow o height en el <ul>. El <ul> se expandirá tan alto como su contenido y es el <div> que realmente está desplazándose. -webkit-overflow-scrolling es heredado, por lo tanto, colóquelo tan lejos como desee.

Demostración: http://jsfiddle.net/ThinkingStiff/FDqH7/

Guión:

var swipeY = 0; 

function onTouchMove(event) { 

    var scroll = event.target.closestByClassName('scroll'); 

    if (scroll) { 

     var top = scroll.positionTop - scroll.parentNode.positionTop, 
      heightDifference = (0 - scroll.offsetHeight + scroll.parentNode.offsetHeight); 

     if((top >= 0) && (event.touches[0].screenY > swipeY)) { 
      event.preventDefault(); //at top, swiping down 
     } else if((top <= heightDifference) && (event.touches[0].screenY < swipeY)) { 
      event.preventDefault(); //at bottom, swiping up 
     }; 

    } else { 
     event.preventDefault(); 
    }; 

}; 

function onTouchStart(event) { 

    swipeY = event.touches[0].screenY; 

}; 

Element.prototype.closestByClassName = function (className) { 

    return this.className && this.className.split(' ').indexOf(className) > -1 
     ? this 
     : (this.parentNode.closestByClassName && this.parentNode.closestByClassName(className)); 

}; 

window.Object.defineProperty(Element.prototype, 'positionTop', { 

    get: function() { 
     return this.offsetTop - this.parentNode.scrollTop; 
    } 

}); 

document.getElementById('viewport').addEventListener('touchmove', onTouchMove, false); 
document.getElementById('viewport').addEventListener('touchstart', onTouchStart, false); 

HTML:

<div id="viewport"> 
<div id="scroll-view"> 
    <ul class="scroll"> 
     <li>scroll scroll scroll scroll scroll </li> 
     <li>scroll scroll scroll scroll scroll </li> 
     <li>scroll scroll scroll scroll scroll </li> 

     . . . 

    </ul> 
</div> 
</div> 

CSS:

#viewport { 
    border: 1px solid black; 
    height: 460px; 
    width: 320px; 
    -webkit-overflow-scrolling: touch; 
} 

#scroll-view { 
    height: 100%; 
    overflow-y: auto; 
    width: 100%; 
} 
+0

He intentado tu código con '# viewport' como una div posicionada ableslute con' overflow: auto' y un montón de _lorem ipsun inside_ y lo que está ocurriendo actualmente es que la secuencia de comandos deshabilitó el desplazamiento de 'viewport' mientras dejaba el desplazamiento animoso en el cuerpo. – zanona

+0

Ponga un div dentro de #viewport y coloque el texto dentro de eso. No establezca el desbordamiento en el div interior, pero coloque un "desplazamiento" de clase si usa el código anterior. Las configuraciones de recorrido para #viewport son correctas para desbordamiento y posición. – ThinkingStiff

+0

@ludicco Actualicé mi respuesta y creé una demostración para que quede más clara. He estado usando esto con éxito desde hace algunos meses. – ThinkingStiff

2

He aquí una respuesta similar a ThinkingStiff de, excepto que no ordena su estructura html Busca elementos que tengan contenido desbordado y permite el desplazamiento solo cuando el usuario interactúa con ellos.

Desventajas:

  • Una vez que el usuario pulsa el límite superior o inferior del nodo desplazable, rebotando dentro de ese nodo no ocurrirá (pero será si flick desde abajo/encima de los límites). Esto probablemente significa que no cumple con sus requisitos de extracción para actualizar :(

  • Hay una diferencia impar de 2px que noté en mis casos de prueba al calcular desplazamientos de desplazamiento.No estoy seguro de donde vino, y es posible que tenga que modificar el valor

CoffeeScript:

# Vertical scrolling behavior overrides. 
# 
# This disables vertical scrolling on the page for touch devices, unless the user is scrolling 
# within an overflowed node. This requires some finessing of the touch events. 
# 
# **NOTE:** This code ends up disabling bounce behavior if the user tries to scroll on a node that 
# is already at its upper or lower limit. 
window$ = $(window) 
initialY = null 
nodeStack = [] 

# When a user begins a (potential) drag, we jot down positional and node information. 
# 
# The assumption is that page content isn't going to move for the duration of the drag, and that 
# it would also be awkward if the drag were to change/stop part way through due to DOM 
# modifications. 
window$.bind 'touchstart', (evt) -> 
    initialY = evt.originalEvent.pageY 
    nodeStack = $(evt.target).parents().andSelf().filter(':not(body, html)').get().reverse() 
    nodeStack = nodeStack.map (node) -> $(node) 

window$.bind 'touchend touchcancel', (evt) -> 
    initialY = null 
    nodeStack = [] 

# We override the `touchmove` event so that we only allow scrolls in allowable directions, 
# depending on where the user first began the drag. 
window$.bind 'touchmove', (evt) -> 
    return evt.preventDefault() if initialY == null 
    # A positive direction indicates that the user is dragging their finger down, thus wanting the 
    # content to scroll up. 
    direction = evt.originalEvent.pageY - initialY 

    for node$ in nodeStack 
    nodeHeight = node$.height() 
    # For some reason, the node's scrollHeight is off by 2 pixels in all cases. This may require 
    # tweaking depending on your DOM. Concerning. 
    scrollHeight = node$[0].scrollHeight - 2 
    nodeScrollTop = node$.scrollTop() 

    # If we have a scrollable element, we want to only allow drags under certain circumstances: 
    if scrollHeight > nodeHeight 
     # * The user is dragging the content up, and the element is already scrolled down a bit. 
     return if direction > 0 and nodeScrollTop > 0 
     # * And the reverse: the user is dragging the content down, and the element is up a bit. 
     return if direction < 0 and nodeScrollTop < scrollHeight - nodeHeight 

    # Otherwise, the default behavior is to disable dragging. 
    evt.preventDefault() 
+0

Guau, ¿qué idioma es ese? – Bergi

+0

CoffeeScript (compila hasta JavaScript; es mucho más conveniente para escribir): http://coffeescript.org/ – Nevir

+0

sí, pero resaltar no es compatible tan bien ... – Bergi

Cuestiones relacionadas