2011-11-08 15 views
9

Sto creando un'applicazione web a schermo intero che avrà alcuni moduli/widget che fanno uso del nuovo overflow di iOS 5: funzioni di scorrimento. Quello che voglio è disabilitare l'effetto "rimbalzante" quando si scorre html/body (dato che è a schermo intero) ma mantenere questo effetto solo sugli elementi scorrevoli.disabilitando lo scorrimento rimbalzante solo per html ma mantenendo gli elementi con overflow: scroll

per attenuare gli effetti di elementi scorrevoli che ho:

html, body { overflow: hidden; } 

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

e quindi il seguente script che disabilita l'effetto tocco di scorrimento:

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

anche se questo non sembra funzionare affatto , perché quando si scorre un elemento in fondo o in alto si scorre anche il documentElement.

C'è un modo per disabilitare solo quell'effetto per l'elemento html del corpo?

Qui si tratta di un buon esempio di come questo influisce sulla funzionalità:

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

+0

Non penso che il gestore di eventi raggiungerà mai preventDefault() perché la destinazione è l'elemento che ha attivato l'evento, che non può mai essere document.documentElement (). Quindi stai vedendo lo stesso comportamento come se non avessi il gestore di eventi. – ThinkingStiff

+0

che sarebbe "currentTarget", temo. l'obiettivo può restituire qualsiasi cosa al suo interno, si potrebbe voler provare;) – zanona

+0

currentTarget restituisce l'elemento con l'ascoltatore, non l'elemento che ha gettato l'evento. – ThinkingStiff

risposta

0

Si scopre per me che l'unica soluzione efficace è stato quello di utilizzare joelambert/ScrollFix sceneggiatura, ha funzionato davvero bene senza ritardi, infatti lo sto già utilizzando in uno dei miei progetti.

È inoltre possibile controllare su di esso in ulteriori dettagli su his blog post. Ci scusiamo per gli altri utenti che hanno risposto, ma davvero non ho trovato quelle risposte per me.

2

E 'un peccato che -webkit-overflow-scrolling non gestisce questo meglio. È necessario tenere traccia della posizione per farlo funzionare. Metto la classe scroll su tutto ciò che voglio scorrere sulla mia pagina, come ad esempio gli elementi <ul>. Avvolgi uno <div> intorno allo <ul> che riempie il viewport con overflow-y: auto. Non inserire overflow o height su <ul>. Lo <ul> si espanderà tanto quanto il suo contenuto ed è lo <div> che sta effettivamente facendo lo scrolling. -webkit-overflow-scrolling è ereditato, quindi mettilo fino al DOM che desideri.

Demo: http://jsfiddle.net/ThinkingStiff/FDqH7/

Script:

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

Ho provato il tuo codice con '# viewport' come un posizionamento posizionato in dissolvenza con' overflow: auto' e un sacco di _lorem ipsun inside_ e ciò che sta accadendo attualmente è che lo script disabilita lo scorrimento di 'viewport' mentre lascia lo scrolling rimbalzante nel corpo. – zanona

+0

Metti un div all'interno di #viewport e inserisci il testo all'interno di esso. Non impostare l'overflow sul div interno, ma mettere un "scroll" di classe su di esso se stai usando il codice sopra. Le impostazioni del tour per #viewport sono corrette per overflow e posizione. – ThinkingStiff

+0

@ludicco Ho aggiornato la mia risposta e ho creato una demo per renderla più chiara. Lo sto usando con successo da alcuni mesi. – ThinkingStiff

2

Ecco una risposta simile a ThinkingStiff di, se non che non impone la tua struttura html. Cerca eventuali elementi che hanno overflow del contenuto e consente lo scorrimento solo quando l'utente sta interagendo con loro.

Inconvenienti:

  • Una volta che l'utente preme il limite superiore o inferiore del nodo scorrevole, rimbalzando all'interno di quel nodo non si verificherà (ma sarà se flick da sotto/sopra i limiti). Probabilmente ciò significa che non soddisfa i requisiti per pull to refresh :(

  • C'è una differenza 2px dispari che ho notato nei miei casi di test durante il calcolo delle scroll scroll.Non so dove che è venuto da, e potrebbe essere necessario modificare il valore

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

Wow, che lingua è? – Bergi

+0

CoffeeScript (si compila in JavaScript - è molto più comodo da scrivere): http://coffeescript.org/ – Nevir

+0

sì, ma l'evidenziazione non è supportata così bene ... – Bergi

Problemi correlati