如何在 iOS 上的 Safari 中滚动时监控滚动位置?

Posted

技术标签:

【中文标题】如何在 iOS 上的 Safari 中滚动时监控滚动位置?【英文标题】:How can I monitor scroll position while scrolling in Safari on iOS? 【发布时间】:2012-02-10 09:28:45 【问题描述】:

我目前使用$(window).bind('scroll', foo); 来监控$(window).scrollTop() 并做一些事情来创建视差效果。

在所有桌面浏览器中,用户滚动的每个像素都会调用foo(),一切都很好。在 ios 上的 Safari 中,滚动事件仅在滚动完成后触发。

我添加了$(window).bind('touchmove', foo); 以确保在 iOS 中滑动期间调用该函数,这让我更进一步。当用户松开手指时,页面继续滚动,但事件停止触发。

有什么想法吗?

【问题讨论】:

【参考方案1】:

当我看到你的问题时,我正计划为此做一个 polyfill(如果不存在的话?)。不幸的是,我的时间很少。

这个想法是有一个setInterval,它被启动ontouchstart,它检查document.body.scrollTop自上次以来是否发生了变化,例如。每 20 毫秒。如果是,那么我们手动调度滚动事件。否则我们clearInterval,因为显然没有更多的滚动发生。

这将是简短的。如果您有更多时间(比我多),请随意尝试这些指南。

编辑:现在,进一步阅读,似乎在另一个答案中提出了相同的想法。您确定在 iPad 上滚动时间隔会停止吗?

【讨论】:

我在hakoniemi.net/labs/onscroll.html 尝试了同样的方法,结果得到了相同的分辨率:iOS 弹性滚动无法被跟踪。它没有事件监听器+滚动期间超时/间隔都不会执行。而且由于iOS5中没有requestAnimationFrame,这似乎是无法解决的。 如果间隔运行失败,您当然不会期望 rAF 运行。但是,FWIW 可以在动量滚动进行时在基于 Web 套接字的 Safari 开发工具中获得最新读数。 嘿,我们可以处理touchmove,而不是setInterval,这可能对berformace不利 确实,滚动时似乎没有执行间隔。【参考方案2】:

我强烈推荐使用“Skrollr”javascript 库。这是迄今为止我发现的最好的移动滚动动画选项,并且很容易快速启动和运行。根据开始和结束滚动位置创建动画和操作 CSS。为大多数标准 CSS 属性创建尽可能多的数据滚动位置和动画。

在以下示例中,背景颜色将在 500 像素滚动过程中进行动画处理:

<div data-0="background-color:rgb(0,0,255);" data-500="background-color:rgb(255,0,0);">WOOOT</div>

在 Git 上签出存储库:https://github.com/Prinzhorn/skrollr

Skrollr 演示示例:http://prinzhorn.github.io/skrollr/

真棒现实世界示例:http://www.fontwalk.de/03/

【讨论】:

感谢您的参考。我正在处理同样的问题,希望 skrollr 能提供帮助,但是通过阅读我已经对此充满信心的很棒的文档。【参考方案3】:

Apple 的 iPhone 5c 网页使用了一些视差滚动效果,似乎在您的手指仍触摸屏幕并滚动时会继续。所以我猜想在滚动期间不能完全禁用javascript。 Tumult Hype 也提供此功能。

【讨论】:

【参考方案4】:

虽然这不可能开箱即用,但可以这么说,您可以使用 iscroll 来做到这一点

因此,您可以将 iScroll 用于 iOS 和 android 移动设备/平板电脑,并使用您目前在桌面设备上使用的方式。

iScroll 有许多选项可用于在某些事件上调用回调函数 - 例如“onScrollMove”、“onBeforeScrollEnd”、“onTouchEnd”等。不幸的是,没有选项可以在“每次位置变化”时执行回调,包括用户停止触摸屏幕后滚动动量引起的变化”。但是,添加一个很容易。

在 iScroll 源代码中,在第 127 行附近,靠近“//Events”注释,添加一个新变量:

onPosChange: null

然后,在第 308 行附近,在“_pos”函数的末尾,添加以下行:

if (this.options.onPosChange) this.options.onPosChange.call();

(如果存在,它将只调用“onPosChange”选项中传递的函数)。

完成后,以下示例代码将为 id="iscroll_container" 的 div 设置 iScroll,并在每次更改时将 Y 偏移量打印到控制台:

var myScroll;
function loaded() 
    myScroll = new iScroll('iscroll_container',  onPosChange: actOnScroll );


document.addEventListener('touchmove', function (e)  e.preventDefault(); , false);

//Use this for high compatibility (iDevice + Android)
document.addEventListener('DOMContentLoaded', function ()  setTimeout(loaded, 200); , false);

function actOnScroll()
    console.log('got a scroll move! Vert offset is: ' + myScroll.y);

注意,Ben the Bodyguard Parallax Site 使用 iScroll 在 iPad 上工作(他们使用的是旧版本的 iscroll,并且不完全按照我在此处描述的方式进行操作)

另外,Life of Pi Parallax Site 在 iPad 上运行得非常好 - 我不知道他们是如何做到的,但至少证明这是可能的!

【讨论】:

【参考方案5】:

这可能是 jQuery 本身的错误:http://bugs.jquery.com/ticket/6446

该票证已经开放了一段时间并且与 iOS 4 相关,但也许您应该研究使用纯 javascript 计算滚动位置。

【讨论】:

【参考方案6】:

据我所知,在大多数移动设备上滚动时不会执行 javascript。 那里有一些解决方法(例如 iscroll)。 Iscroll 正在使用 css 技术“转换”。 但是滚动时无法执行javascript。 我想平滑滚动算法太贵了。

【讨论】:

以上是关于如何在 iOS 上的 Safari 中滚动时监控滚动位置?的主要内容,如果未能解决你的问题,请参考以下文章

触摸事件仅在iPad iOS 11.4上的Mobile Safari中滚动时触发“一次”

iOS 上的 Safari 仅在滚动停止后显示固定元素

IFRAMEs 和 iPad 上的 Safari,用户如何滚动内容?

如何强制 Safari 重新绘制位置:滚动上的固定元素?

如何从 IOS Safari 中的 touchmove 事件中检测滚动画布

在 iOS Safari 中使用 iScroll 和输入时,键盘会将滚动条推到视口上方并卡住