屏幕方向改变事件触发滚动和调整大小事件。

5

我正在处理一个项目,遇到了一个奇怪的问题,在这里(或任何其他地方)我都找不到答案。

我尝试创建一个Fiddle来演示发生了什么,但由于我的脚本的性质以及jsfiddle的工作方式,它无法正常工作。无论如何,这是Fiddle的链接,所以至少您会有代码。

我想要发生的事情

在三个可能的window事件上执行单个处理程序(onViewportChange):resizeorientationchangescroll。根据事件类型,处理程序将弄清楚该做什么。听起来非常简单。

我做了什么

对于此示例,我将处理程序限制为回显事件类型,用于测试目的:

var onViewportChange = function(e) {
    alert(e.type);
};

我将处理程序绑定到事件:(我也尝试过使用事件数组和多个单独的绑定来绑定.bind()
$(window).on({
    'orientationchange resize scroll' : function(e){
        onViewportChange(e);
    }
});

HTML完全为空,除了任意的基本元素(doctype、html、body,当然还有jquery和这个脚本)。
实际发生的情况是这样的:桌面浏览器上事件正常触发(主要是因为没有orientationchange事件的触发),但在移动设备上却不行(在iOS6+ iPad第三代和iOS6+ iPhone 5上测试过)。当我旋转我的设备时:
- iPad和iPhone都会触发三个事件:orientationchangeresize,然后是scroll - iPhone上的Chrome会触发resize,然后是orientationchange - 我借来的Android手机会触发orientationchange,然后是resize (请注意,由于竞态条件,事件顺序可能不准确。)
这就是我将其与orientationchange事件相关联的原因:当我移除orientationchange事件(只留下resizescroll)时,设备旋转时只触发scroll事件,而不再触发resize事件。
我不明白为什么所有事件会同时触发。至少,我可以想象在orientationchange上触发resize,因为窗口尺寸发生变化,但是scroll呢?
有人知道为什么会发生这种情况吗?
编辑:我在这里设置了一个演示:http://beta.hnldesign.nl/orientation/index.html

5
据说移动版 Safari 在重新构建/重新评估 window.scrollTopwindow.scrollLeft 值时会触发 resize 事件。您可以使用一个标记来避免触发 scroll 事件以解决此问题。请注意不要改变原文意思,同时尽量使翻译通俗易懂。 - inhan
1
我想象中是因为Safari尝试在方向改变之前将用户滚动到页面上的某个位置,所以会触发scroll事件... - MassivePenguin
谢谢inhan,但我该如何区分“scroll”的重新评估和实际用户的“scroll”? - Klaas Leussink
你能否在 orientationchange 事件上设置一个标志(并在短时间内重置该标志),并在调用 scroll 事件时检查该标志?或者你不能保证 orientationchange 总是在 scroll 之前被调用? - MassivePenguin
恐怕我不能保证。问题在于orientationchange和滚动事件由于竞争条件而冲突;无论哪个先触发都会获得胜利。这很令人烦恼。 - Klaas Leussink
1个回答

4
嗯,可以试试这个方法(从jQuery API文档中提取...)http://api.jquery.com/on/
$(window).on({
  orientationchange: function(e) {
    onViewportChange(e);
  }, resize: function(e) {
    onViewportChange(e);
  }, scroll: function(e) {
    onViewportChange(e);
  }
});

这应该可以工作... 也许您需要稍微调整一下代码


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接