在 iOS MobileSafari 中阻止默认按下但不阻止默认拖动?
上下文:MobileSafari/iPad 上的 Web 应用程序,全屏并嵌入 iframe
目标:为新闻和<提供自定义事件处理程序的技术em>点击,但不捏合(缩放)或拖动(滚动/平移)。我们希望为 Press 提供自定义行为,但仍让 Safari 处理滚动/平移/缩放。
问题:这两个目标似乎是相互排斥的。要阻止按下手势的默认行为,必须在立即响应 ontouchstart。但是,为了让默认行为在 Drag 上继续进行,我们必须不在初始 ontouchstart 上调用 event.preventDefault。一旦调用了preventDefault,就无法在该手势序列期间恢复默认行为(即直到所有手指都松开)。在发生某些移动之前,无法识别拖动。
拖动是最简单的示例,但我们也关心获得捏合和双击的默认行为。我们永远不希望默认的 MobileSafari Press 行为为“复制图像”或选择文本。
到目前为止的尝试:
- 保存 ontouchstart 事件,并在 超时之后,调用 PreventDefault on稍后(就在 Press 被识别之前)。没有效果。
- 监听“oncontextmenu”。不,默认的新闻行为不会通过此事件发出信号或路由。
- 防止我们所有 ontouch* 处理程序中的默认情况,然后当我们识别拖动/捏合手势时,使用 initTouchEvent 和/或 initGestureEvent。以编程方式创建的事件会触发我们的所有回调,但 Safari 似乎没有注意到它们,也没有触发默认行为。
- 用假动作破坏 Safari 的按压识别。 Safari 会取消最轻微的移动,但我们允许有一点倾斜。如果手指没有“真正”移动,在 ontouchstart 之后模拟移动事件(如上所述)不会导致 Safari 无法识别 Press。
我们拥有一套功能齐全的手势识别器,以 Apple 原生 iOS 手势识别器。我们识别任何手势都没有问题,只是不知道有什么好方法来复制 Safari 免费提供的缩放/平移/双击行为。
我们不需要代码;我们正在寻找任何理论上的解决方案(除了“自己也实现平移/缩放”之外,尽管如果您有一种巧妙的方法,我们对此很感兴趣),以带来合理的成功。我们也有兴趣了解其他类似的尝试 - 我们肯定不能成为第一个尝试这个的吗?
备用 TL;DR: 除了在 touchstart 中之外,还有什么方法可以防止默认按下(也称为点击并按住)吗?
Context: Web app on MobileSafari/iPad, both full-screen and embedded in iframe
Goal: Technique that provides custom event handlers for Press and Tap but not Pinch (zoom) or Drag (scroll/pan). We want to provide custom behavior for Press, but to let Safari handle Scroll/Pan/Zoom still.
Problem: The two goals seem to be mutually exclusive. To prevent the default behavior for a Press gesture, event.preventDefault must be called in immediate response to ontouchstart. However, to let the default behavior proceed on a Drag, we must not call event.preventDefault on the initial ontouchstart. Once preventDefault is called, there is no way of getting the default behavior back during that gesture sequence (i.e. until all fingers come off). Drag is not recognized until some movement has occurred.
Drag is illustrated as the simplest example, but we care about getting the default behavior for Pinch and Double-tap as well. We never want the default MobileSafari Press behavior of "Copy Image" or selecting text.
Attempts thus far:
- Save the ontouchstart event and, after a timeout, call preventDefault on it later (just before Press would be recognized). No effect.
- Listen for 'oncontextmenu'. Nope, the default Press behavior is not being signaled or routed through this event.
- Prevent the default in all of our ontouch* handlers, and then when we recognize a Drag/Pinch gesture, simulate new events using initTouchEvent and/or initGestureEvent. The programmatically created events hit all of our callbacks, but Safari seems to pay no attention to them, triggering no default behavior.
- Break up Safari's Press recognition with a fake move. Safari cancels a press on the slightest move, but we allow for a bit of slop. Simulating a move event (as above) just after the ontouchstart does not cause Safari to fail to recognize Press if the finger is not moved "for real".
We have a fully featured set of gesture recognizers implemented (in Javascript, ontouch*) in the style of Apple's native iOS gesture recognizers. We have no problem recognizing any gestures, we just don't know of a good way to replicate the Zoom/Pan/Double-tap behavior that Safari provides for free.
We don't need code; we're looking for any theoretical solution (beyond "just implement pan/zoom yourself too", though if you have a slick way of doing that we're interested) that leads to reasonable success. We're also interested in learning about other similar attempts to do this - surely we can't have been the first to try this?
Alternate TL;DR: Is there any way to prevent a default Press (also known as tap-and-hold) other than in touchstart?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
成功:完全通过CSS而不是preventDefault来防止“默认按下”行为。此答案由 Safari 技术传播者 Vicki Murley 通过 此处(需要注册)
评论:我们假设 Safari 的 Press 行为是基于事件的,而不是由 CSS 驱动的。调用 PreventDefault ontouchstart 确实会取消按下行为(这确实导致我们误入歧途),但这似乎是一个意想不到的副作用。实际上,Mobile Safari 并不执行“按下事件”,而是执行“按下时的 CSS”。
使用 CSS 禁用 Press 行为使我们能够仅在真正需要的地方和时间再次调用 PreventDefault。
Success: Prevent "default press" behavior entirely through CSS instead of preventDefault. This answer was provided by Safari Technologies Evangelist Vicki Murley over here (registration required)
Commentary: We assumed that Safari's Press behavior was event-based, not driven by CSS. Calling preventDefault ontouchstart does cancel the press behavior (which is what led us astray, really), but that seems to be an unintended side-effect. Really, Mobile Safari does not execute a "press event" so much as "CSS on press".
Disabling the Press behavior with CSS has allowed us to once again call preventDefault only where and when we actually need it.
丑陋的可能性:不阻止按下 - 让默认按下不执行任何操作。尝试使用玻璃窗格 div 来捕获所有触摸并且不会阻止 touchstart 上的任何操作。
Div 确实有默认的 Press 行为(某种选择),但也许可以通过
来关闭,而不是通过 PreventDevault 来关闭? ref
这意味着我们必须进行自己的命中测试来确定哪些 DOM 节点将我们识别的事件传递给,因为我们不能让事件在 DOM 祖先链中向上冒泡。
Ugly Possibility: Don't prevent a press - make a default press do nothing. Try to use a glass-pane div that catches all touches and doesn't prevent anything on touchstart.
Divs do have default Press behavior (some kind of selection), but perhaps that can be turned off, not via preventDevault but via
<body style="-webkit-user-select:none">
? refThis would mean we'd have to do our own hit-testing to determine what DOM nodes to pass our recognized events to, since we can't just let events bubble up the DOM ancestor chain.