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

我需要保持一个元素的滚动偏移量与另一个元素(窗口实际上)保持同步,并且在移动Safari(iPad)上滚动的惯性“滚降”阶段时遇到问题。

我有一些position:fixed; overflow:hidden的div position:fixed; overflow:hidden position:fixed; overflow:hidden ,我需要保持它们的滚动偏移量与窗口的滚动偏移量一致(意味着整个滚动体)。通常我会这样编写代码(jQuery):

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

$win.scroll(function() { 
    $div1.scrollTop($win.scrollTop())
})

但是在iPad上测试界面时,我注意到在触摸阶段,当您用手指拖动虚拟页面时,也没有在惯性阶段,当您放开并且页面变慢时,div没有被更新一站。

我通过注册touchmove事件的处理程序以及scroll来解决它在拖动阶段的问题。

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

这是一个工作演示。

尝试在iPad上滚动以查看“惯性滚动”问题。 不幸的是,我不能让它在jsFiddle上工作,这是由于iPad在iframe滚动时的奇怪行为。

如果我可以在这个阶段进行轮询,我可以保持两个元素之间的同步。 我尝试过使用setTimeoutsetIntervalrequestAnimationFrame ,但它们都不在惯性滚动阶段触发。 似乎所有的JavaScript都停在这个阶段。

问题:

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

  • 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
        });
    })
    

    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;
    
    }
    

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


    在惯性滚动发生时,iOS实际上冻结了DOM操作和Javascript。 下面是一个简单的演示,我用它来说明在普通桌面环境和iPad之间滚动的区别:http://jsfiddle.net/notjoelshapiro/LUcR6/。 这段代码只有这个JS:

    var num = 0;
    function updateNum(){
        num++;
        $('#awesomeDiv').text(num);
    }
    $(window).scroll(updateNum);
    

    在滚动时,它会增加一个数字并将其显示在页面的底部。 您会看到屏幕底部的滚动编号只在惯性滚动停止时增加。 如果Javascript在后台运行,它将不会刷新,直到滚动结束,但数字应该增加更高。

    所以要专门回答你的问题:

    惯性滚动阶段是否触发或滚动事件?

    负面的,ghostrider。

    有没有什么办法在这个阶段运行Javascript回调?

    往上看。

    有没有办法使用CSS或JS以外的其他技术来同步两个元素(X或Y,不是两者)的滚动偏移量?

    不太清楚你在这里的含义,JS可以完成你需要的所有数学运算,但是当惯性滚动完成时它必须是。 说实话,这可能是tl; dr以来的症状,因为我现在正在工作。

    你看过iScroll库吗? 它模拟触摸和非触摸环境的惯性(或非惯性)滚动,并在“滚动”和“惯性滚动”期间/之后为您提供JS回调,并提供大量可用于计算您在哪里页。


    滚动开始时触发。 请注意,iOS设备在滚动过程中冻结DOM操作,在滚动完成时排队它们以应用。 我们目前正在研究在滚动开始之前允许应用DOM操作的方法。

    http://jquerymobile.com/demos/1.0rc1/docs/api/events.html#/demos/1.0rc1/docs/api/events.html

    那就是他们在滚动开始部分下所要说的

    链接地址: http://www.djcxy.com/p/95623.html

    上一篇: How to synchronize the scroll offset of two elements during inertial scrolling

    下一篇: Understanding touch events