如何在 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中滚动时触发“一次”
IFRAMEs 和 iPad 上的 Safari,用户如何滚动内容?