2011-11-08 16 views
9

Yeni iOS 5 taşma: kaydırma özelliklerini kullanan bazı modüllere/parçacıklara sahip tam ekran web uygulaması oluşturuyorum. İstediğim şey, html/body (tam ekran olduğu için) kaydırırken 'bu' kabarıklık 'etkisini devre dışı bırakmaktır, ancak bu etkiyi yalnızca kaydırılabilir öğelerde korur.Sadece html için kaydırma kaydırma işlevini devre dışı bırakan ancak taşması olan öğeleri koruyarak: kaydırma

html, body { overflow: hidden; } 

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

ve ardından dokunmatik kaydırma efekti devre dışı bırakır Aşağıdaki komut dosyası: hiç işe görünmüyor bu halde

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

Ben kaydırılabilir elementlerin etkilerini yumuşatmak için Çünkü bir elemanı çok alttan sona veya üstüne kaydırırken documentElement'u da kaydırır.

Yalnızca vücut html öğesi için bu efekti devre dışı bırakmanın bir yolu var mı?

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

+0

Olay işleyicinizin hiç bir zaman failDefault() öğesini vuracağını sanmıyorum çünkü hedef, olayı tetikleyen öğedir, bu asla document.documentElement () olamaz. Yani, olay işleyicisine sahip olmamış gibi aynı davranışı görüyorsunuz. – ThinkingStiff

+0

bu "currentTarget" olacak korkarım. hedef, içindeki herhangi bir şeyi döndürebilir, denemek isteyebilirsiniz;) – zanona

+0

currentTarget, olayı atan öğeyi değil, öğeyi dinleyiciyle döndürür. – ThinkingStiff

cevap

0

Sadece etkili çözüm joelambert/ScrollFix senaryoyu kullanmak olduğuna benim için çıkıyor, gerçekten işe yaradı Hiçbir gecikme olmadan, Aslında ben zaten projelerimden birinde kullanıyorum.

Ayrıca, his blog post numaralı telefondan daha ayrıntılı bilgi alabilirsiniz. Yanıt veren diğer kullanıcılar için üzgünüm, ama bu cevapları benim için işe almadım.

2

O -webkit-overflow-scrolling bu daha iyi idare etmediğini talihsiz:

İşte bu işlevi nasıl etkilediğini iyi bir örnektir. Çalışması için y konumunu izlemeniz gerekir. Sayfamda, <ul> öğeleri gibi kaydırmak istediğim bir şeye, scroll sınıfını ekledim. Görüntüyü overflow-y: auto ile dolduran <ul> çevresine sarın. <ul>'a overflow veya height'u yerleştirmeyin. <ul>, içeriği kadar yüksek olacak ve aslında kaydırma işlemini yapan . -webkit-overflow-scrolling, devralınmıştır, bu yüzden DOM'u istediğiniz kadar uzatabilirsiniz.

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

Senaryo:

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

Kodunuzu denedim '# viewport' ile bir aboslute konumlandırılmış div 'overflow: auto' ve çok sayıda _lorem ipsun inside_ ile ve şu anda gerçekleşen şudur: Script vücutta bouncy kaydırmayı bırakırken 'viewport' kaydırma işlemini devre dışı bırakmıştır. – zanona

+0

#viewport'un içine bir div koyun ve metni bunun içine koyun. İçteki divda taşma ayarlamayın, ancak yukarıdaki kodu kullanıyorsanız bir "scroll" yazınız. #viewport için tur ayarları taşma ve konum için doğrudur. – ThinkingStiff

+0

@ludicco Cevabımı güncelledim ve daha net olması için bir demo oluşturdum. Bunu birkaç aydır başarıyla kullanıyorum. – ThinkingStiff

2

İşte ThinkingStiff en benzer cevabı bunun dışında bulunuyor html yapınızı zorunlu kılmaz. Taşan içeriğe sahip olan ve yalnızca kullanıcı onlarla etkileşime geçtiğinde kaydırma yapabilen tüm öğeleri arar.

Downsides: kullanıcı (ancak bu sınırların üzerinde/alttan fiske eğer) meydana gelmeyeceği konusunda düğüm içinde zıplayan, kaydırılabilir düğümün üst veya alt limite ulaştığında

  • kez. Bu muhtemelen, yenileme için gereksinimlerinizi karşılamadığı anlamına gelir :(

  • Kaydırma ofsetlerini hesaplarken test durumlarımda fark ettiğim tuhaf bir 2px farkı var.Bunun geldiği ve değerini

CoffeeScript ince ayar gerekebilir emin değilim burada:

# 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

Vay, hangi dil bu? – Bergi

+0

CoffeeScript (JavaScript'e derler - sadece yazması çok daha kolay): http://coffeescript.org/ – Nevir

+0

evet, ancak vurgulama o kadar iyi desteklenmiyor ... – Bergi

İlgili konular