отключение оживленной прокрутки только для html, но ведение для элементов с переполнением: scroll - PullRequest
9 голосов
/ 08 ноября 2011

Я создаю полноэкранное веб-приложение, в котором будут некоторые модули / виджеты, использующие новое переполнение iOS 5: функции прокрутки. То, что я хочу, это отключить этот эффект «бодрости» при прокрутке html / body (поскольку это полноэкранный режим), но сохранить этот эффект только для прокручиваемых элементов.

чтобы сгладить эффекты прокручиваемых элементов у меня есть:

html, body { overflow: hidden; }

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

, а затем следующий скрипт, который отключает эффект сенсорной прокрутки:

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

хотя это, похоже, не работает вообще, потому что при прокрутке элемента к самому низу или верху он также прокручивает documentElement.

Есть ли способ отключить этот эффект только для элемента body html?

Вот хороший пример того, как это влияет на функциональность:

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

Ответы [ 3 ]

2 голосов
/ 18 февраля 2012

Вот аналогичный ответ ThinkingStiff, за исключением того, что он не требует вашей HTML-структуры. Он ищет любые элементы с переполненным содержимым и обеспечивает прокрутку только тогда, когда пользователь взаимодействует с ними.

Downsides:

  • Как только пользователь достигнет верхнего или нижнего предела прокручиваемого узла, отскок внутри этого узла не произойдет (но это произойдет, если вы щелкнете ниже / выше пределов). Это, вероятно, означает, что он не удовлетворяет вашим требованиям для обновления до: (

  • Существует странная разница в 2 пикселя, которую я заметил в своих тестах при расчете смещения прокрутки. Не уверен, откуда это взялось, и вам может понадобиться настроить значение

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()
2 голосов
/ 11 ноября 2011

К сожалению, -webkit-overflow-scrolling не справляется с этим лучше. Вам нужно отследить позицию y, чтобы она заработала. Я поместил класс scroll на все, что я хочу прокрутить на своей странице, например <ul> элементы Оберните <div> вокруг <ul>, который заполняет область просмотра overflow-y: auto. Не ставьте overflow или height на <ul>. <ul> расширится так же высоко, как и его содержимое, а именно <div> выполняет прокрутку. -webkit-overflow-scrolling наследуется, поэтому поместите его как можно дальше в DOM.

Демо: http://jsfiddle.net/ThinkingStiff/FDqH7/

Сценарий:

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 голосов
/ 26 августа 2012

Оказалось, что единственным эффективным решением было использование сценария joelambert / ScrollFix , который работал очень хорошо без задержек, фактически я уже использую его в одном из своих проектов.

Вы также можете узнать об этом подробнее в своем блоге . Извините за других пользователей, которые ответили, но я действительно не получил эти ответы для меня.

...