如何在惯性滚动期间同步两个元素的滚动偏移

Tob*_*bia 7 scroll mobile-safari ipad touchmove

我需要保持一个元素的滚动偏移量与另一个元素(实际上是窗口)保持同步,并且我在移动Safari(iPad)上滚动的惯性"滚动"阶段遇到了麻烦.

我有几个div,position:fixed; overflow:hidden我需要保持他们的滚动偏移与窗口的一个同步(意味着整个身体滚动.)通常我会像这样(jQuery)编码:

var $win = $(window),
    $div1 = $(...)

$win.scroll(function() { 
    $div1.scrollTop($win.scrollTop())
})
Run Code Online (Sandbox Code Playgroud)

但是在iPad上测试界面时,我注意到在触摸阶段,当你用手指拖动虚拟页面时,也没有在惯性阶段,当你放开并且页面减速到停下来

我通过注册touchmove事件的处理程序以及事件处理程序来解决拖动阶段scroll.

但我找不到解决惯性阶段问题的方法.div保持静止(并且慢慢地与页面的其余部分不同步),直到惯性运动达到完全停止,此时滚动事件最终被触发并且它跳到位置.

这是一个有效的演示.

尝试在iPad上滚动它以查看"惯性晃动"问题.不幸的是,我无法让它在jsFiddle上工作,因为iPad在iframe滚动时出现奇怪的行为.

如果我可以在该阶段进行轮询,我可以保持两个元素之间的同步.我试过了setTimeout,setIntervalrequestAnimationFrame,但是在惯性滚动阶段它们都没有发射.似乎所有Javascript都在此阶段停止.

问题:

  • 在惯性滚动阶段是否有触发或滚动事件?
  • 没有办法在该阶段运行Javascript回调?
  • 有没有办法使用CSS或JS以外的其他技术同步两个元素(X或Y,而不是两者)的滚动偏移?

Nic*_*ght 4

OldDrunkenSailor 比我先建议了iScroll

不幸的是,开箱即用的 iScroll 只是复制了与本机惯性滚动相同的问题 - 在惯性阶段没有事件处理。

这是您的演示版本,其中包含猴子修补的 iScroll,以添加即使在惯性阶段也会触发的自定义事件:https://dl.dropbox.com/u/15943645/scrollingdemo.html

在我的第二代 iPad 上运行良好。

JS:

// Disable touch events
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);

// Patch iScroll for position change custom event
iScroll.prototype._oldPos = iScroll.prototype._pos;
iScroll.prototype._pos = function(x, y) {
    this._oldPos(x, y);
    if (this.options.onPositionChange) this.options.onPositionChange.call(this);
}

$(function() {
    var $win = $(window),
        $div_cols = $('#cols'),
        $div_rows = $('#rows'),
        $div_body = $('#body')

    // attach scrolling sync handler and execute it once
    function sync_scroll(e) {
        $div_cols.scrollLeft(0 - $div_body.position().left);
        $div_rows.scrollTop(0 - $div_body.position().top);

    }           

    // initialize iScroll on wrapper div, with position change handler
    var myScroll = new iScroll('iscroll_wrapper', {
        bounce: false,
        onPositionChange: sync_scroll
    });
})
Run Code Online (Sandbox Code Playgroud)

CSS:

#iscroll_wrapper {
    position:absolute;
    z-index: 1;
    left: 168px; 
    top:77px; 
    bottom:0px; 
    right:0;
    overflow:auto;
}

#body {
    position:absolute;
    z-index: 1;
    width: 2046px; 
    height: 3376px;

}
Run Code Online (Sandbox Code Playgroud)

请注意,只有主体响应触摸事件,但您可以将该技术扩展到行和列 div 以获得相反的关系。