【问题标题】:How to synchronize the scroll offset of two elements during inertial scrolling惯性滚动时如何同步两个元素的滚动偏移量
【发布时间】:2013-02-24 14:55:05
【问题描述】:

我需要使一个元素的滚动偏移量与另一个元素(实际上是窗口)保持同步,但在 Mobile Safari (iPad) 上滚动的惯性“滚降”阶段,我无法做到这一点。

我有几个带有position:fixed; overflow:hidden 的 div,我需要使它们的滚动偏移量与窗口的滚动偏移量保持同步(即整个正文滚动。)通常我会这样编码(jQuery):

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

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

但是在 iPad 上测试界面时,我注意到 div 在触摸阶段(用手指拖动虚拟页面时)都没有更新,在惯性阶段(当您放开页面时)也没有更新减速到停止。

我通过为touchmove 事件和scroll 事件注册处理程序解决了拖动阶段的问题。

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

Here's a working demo.

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

如果我可以在那个阶段运行轮询,我可以在两个元素之间保持同步。我试过setTimeoutsetIntervalrequestAnimationFrame,但在惯性滚动阶段它们都不会触发。似乎所有 Javascript 在该阶段都停止了。

问题:

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

【问题讨论】:

  • 将div元素作为子元素添加到滚动层是否可行?
  • “滚动层”是什么意思?被滚动的元素是窗口,也就是整个主体。固定的 div 在 body 内部,是的,但它们有 position:fixed
  • 我基本上是在了解我在这里得到的信息developer.apple.com/library/ios/#documentation/WindowsViews/…
  • 我添加了一个重现问题的工作演示。请忽略大量的 HTML 和 CSS。如果您希望查看元素结构及其 CSS,您可以使用浏览器的检查器,但实际上,理解问题所需的一切都在我的问题中表达了。谢谢。

标签: ipad scroll mobile-safari touchmove


【解决方案1】:

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

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

这就是他们在滚动开始部分所说的话

【讨论】:

  • 谢谢,但该修复与我的问题无关。这不是硬件加速错误。没有消失的元素。这是在自动“惯性”滚动阶段未触发 Javascript 事件的问题。
  • 哦,我觉得他们只是落后了
  • 这是您对 win.scroll 的完整调用吗?
  • 这是一个非常简单的调用。完整的代码以这种方式同步了几个 div。我担心文档参考没有做任何事情。
  • 好吧,祝你好运。我只知道滚动可以快速触发事件处理程序,可能会占据焦点,所以我认为它需要中断。祝你好运
【解决方案2】:

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

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

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

所以专门回答你的问题:

在惯性滚动阶段是否触发了任何触摸或滚动事件?

否定的,幽灵骑士。

有没有办法在那个阶段运行 Javascript 回调?

见上文。

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

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

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

【讨论】:

  • 感谢您的研究。我没有想过用库完全取代原生滚动,但这是一种非常有意义的解决方法。我希望我可以将赏金奖励给尼克,因为他的工作演示。
【解决方案3】:

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 以实现反向关系。

【讨论】:

  • 我没有想过用库完全取代原生滚动,但这是一种非常有意义的解决方法。谢谢@OldDrunkenSailor 和尼克。奖励给尼克的工作演示!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多