13

在 iOS 7 Safari 中,现在有两种向后/向前导航的方式——使用底部的传统向后/向前按钮箭头或从屏幕边缘滑动。我正在使用动画在我的 ajax 应用程序中的页面之间进行转换,但是如果用户通过边缘滑动导航,我不想触发该转换,因为这本身就是一个动画。

但是,两种导航类型的 popstate 事件对象似乎是相同的——有没有办法区分这两种类型的用户导航,以便我们做出相应的响应?

更新:我能够使用(似乎是)iOS7 Safari 中的一个错误来正确检测边缘滑动与后退按钮点击。错误是使用边缘滑动时不会触发 touchend 事件(直到下一个触摸事件)(但 touchstart 和 touchmove 是)。所以我设置了一个shouldAnimate标志并在 touchmove 上禁用它——然后如果标志被禁用并且 popstate 发生,我知道这是一个边缘滑动。

99% 的时间都是正确的——唯一可能失败的情况是用户边缘滑动部分然后放手让当前页面重新回到原位(此时我的标志仍将被禁用)然后点击后退按钮(不触发触摸事件)。为了处理最后一个 [edge] 情况,我在 touchmove 上设置了一个计时器,以在 50 毫秒后重新启用该标志。

是的,它很“脏”,但现在它几乎在所有情况下都能得到我想要的,所以我可以接受——直到苹果修复了这个错误,但希望他们也会在 popstate 事件对象中提供一个指示符来告诉我们它是一种什么样的导航。

4

2 回答 2

1

简短而悲伤的回答:不。这种向后/向前滑动不会传播到实际页面,而是发生在操作系统级别。

于 2013-10-29T15:50:26.517 回答
1

您可以通过监视触摸事件来跟踪边缘拖动导航。如果用户在屏幕边缘的某个阈值内开始拖动,则会触发边缘拖动导航转换。

我在这里写了一个关于如何使用 React 代码监控和采取行动的扩展解释:https ://gist.github.com/MartijnHols/709965559cbdb6b241c12e5866941e69 。基本检测部分可以在常规 JavaScript 中实现,如下所示:

window.isEdgeDragNavigating = false

const IOS_EDGE_DRAG_NAVIGATION_THRESHOLD = 25

let timer
const handleTouchStart = (e) => {
  if (
    e.touches[0].pageX > IOS_EDGE_DRAG_NAVIGATION_THRESHOLD &&
    e.touches[0].pageX <
      window.innerWidth - IOS_EDGE_DRAG_NAVIGATION_THRESHOLD
  ) {
    return
  }

  window.isEdgeDragNavigating = true
  if (timer) {
    clearTimeout(timer)
  }
}
const handleTouchEnd = () => {
  timer = setTimeout(() => window.isEdgeDragNavigating = false, 200)
}

document.addEventListener('touchstart', handleTouchStart)
document.addEventListener('touchend', handleTouchEnd)
于 2021-11-11T09:32:56.210 回答