【问题标题】:how to launch a webpage on mobile web application without scroll如何在没有滚动的情况下在移动 Web 应用程序上启动网页
【发布时间】:2020-10-07 17:02:45
【问题描述】:

编辑澄清:

我想要什么:

一个全屏 javascript 画布,可以处理触摸事件而无需浏览器进一步解释这些事件,但也保留打开用户操作的新窗口的能力。

示例:

  • 我应该能够在不尝试滚动网页的情况下四处滑动手指
  • 我应该能够在不以任何方式轻推网页内容的情况下四处滑动手指(通常,当滚动到滚动区域的末尾时,浏览器允许一些额外的弹簧加载缓冲区滚动以发出信号用户认为它是滚动区域的结尾)。
  • 我应该能够在不缩放网页的情况下进行捏合和平移
  • 等等……

重点:

我需要准确和实时地解释这些事件,以在画布内对这些动作做出反应。 (我正在通过requestAnimationFrame 进行实时绘图,允许我在不使用 DOM 的情况下对用户事件做出反应)

目前的情况:

这一切都完美无缺(除了打开新窗口的能力)因为我将画布定位为视口的完整大小(处理任何窗口调整大小事件),并且画布会监听到ontouchstartontouchmoveontouchend 等事件,在我自己处理了用户输入后调用evt.preventDefault()。这样可以确保画布始终全屏显示,不会移动,并且用户输入准确地提供给我以在游戏中处理。

问题:

我需要处理的一些用户输入是当他们使用“启动我的网页”按钮单击我的画布区域时启动网页。但是,window.open(mywebpage) 不起作用,因为移动 Safari 仅允许在 click 事件的调用堆栈中执行此类操作。因为我依靠ontouchstart 来获得响应式控件,并且evt.preventDefault()ontouchstart 事件中取消了click 事件的发生,所以我无法启动网页(它被浏览器阻止)。

我尝试的解决方案,以及为什么它们不够:

  • 只需使用单击事件而不是 ontouchstart:这意味着我无法阻止滚动/等...此外,它的响应速度不快,并且不允许我很好地处理触摸和拖动事件。
  • 在启动网页区域上方的画布顶部覆盖div(或a)标签,并为其添加点击事件:如果用户点击并拖动在此标签内开始 em>,然后它允许页面滚动和缩放。尝试解决此问题会导致与以前相同的问题。

原帖:

我有一个移动应用程序,它是一个全屏画布,它会在位置上锁定自身(不能滚动或缩放),以便我可以不间断地正确解释用户输入(滑动、平移等...)。

它通过拦截touchstart 事件并调用evt.preventDefault(以及据我所知实际上并没有做任何事情的元视口无缩放东西?)来锁定自己。

这很好用,对于制作游戏(或类似游戏的应用程序)功能是绝对必要的。

问题是我还有一个“转到此网页”按钮。我可以拦截touchstart,并使用window.open(somewebpage),但移动弹出窗口阻止程序会阻止它。 “规则”似乎是“如果网页在用户交互的调用堆栈中完成,并且该交互是“点击”事件,则允许打开网页”。

我已将第一部分记录下来,但如果我将事件更改为 click 事件,则网页现在将滑动解释为滚动(并将捏合解释为缩放等)。如果我同时有clicktouchstart 事件,那么在touchstart 上调用evt.preventDefault()(它会停止滚动/缩放)也会停止click 事件。

如果我在“启动网页”按钮的点击区域顶部覆盖div,那么玩家可以滚动/缩放当他们从该按钮开始输入时,这会导致不可预测的和不稳定的体验。

如何在不让当前网页滚动的情况下启动另一个网页?

编辑:根据要求,这是一个代码 sn-p 至少部分说明了我正在尝试做的事情https://jsfiddle.net/phildo/0q8e47fk/10/。 请注意,在“真实”情况下,画布占据了屏幕的整个宽度/高度,并在屏幕调整大小时进行了相应的显式设置。

【问题讨论】:

标签: javascript html canvas mobile


【解决方案1】:

防止移动网页上的任何类型的反弹是整个移动设备的一个大问题,而不取决于制造商。几年前我在 Windows Phone 8 应用程序上遇到过类似的问题,并且(非常令人惊讶)有一个专用于 Windows 环境的解决方案,当然不能在这里应用。

对于 iOS,您需要 iOS 解决方案,对吗?

这个解决方案被命名为iNoBounce。我们的想法是将js 小库添加到您的 html 页面,具有一些良好约定的代码和 js 库将在必要时完成防止默认值的肮脏工作。

它的实际作用不是阻止任何事情,而是仅仅阻止那些“额外的”并且会导致反弹事件的事情。

iNoBounceGitHub自述的话:

iNoBounce 通过检查新的CSSStyleDeclaration 上的属性来检测浏览器是否支持-webkit-overflow-scrolling。如果是这样,iNoBounce 将侦听touchmove 并选择性地preventDefault() 处理move 事件,这些事件不会发生在具有-webkit-overflow-scrolling: touch 设置的元素的子元素上。此外,iNoBounce 将在用户试图滚动超出scrollable 元素的边界时preventDefault(),防止元素本身出现橡皮筋(不可避免的警告)。

示例代码要求您使用以下部分(canvas 有单独的示例代码,这只是最常见的解决方案):

// All you need is an element with `height` or `max-height`, `overflow: auto` and `-webkit-overflow-scrolling: touch`.

<script src="inobounce.js"></script>

<style>
    ul {
        height: 115px;
        border: 1px solid gray;
        overflow: auto;
        -webkit-overflow-scrolling: touch;
    }
</style>

来源:

[1]https://github.com/lazd/iNoBounce

编辑:

我发现您并不局限于 iOS。对于其他浏览器,请尝试

[2]https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior

其中引入了overscroll-behavior 设置,您可以将其设置为none 以禁用反弹。

它只适用于 Android,不适用于 ie 或 iOS。

对于移动 Windows Phone,我有这样的解决方案:

  div.wp8ScrollFix {
         -ms-touch-action: none;
   }

它的作用与 iNoBounce 相同,现在为包含画布的 div 使用单个 CSS 行。

编辑2:

对于半通用解决方案的搜索,我可以找到

  -touch-action: none;

应用于包含画布的 div 元素,您可以禁用默认触摸事件,并为画布定义您自己的事件。

该解决方案适用于 Safari 浏览器以外的任何其他浏览器。如 [3] 中可能有一些变体,如

   -ms-touch-action: none;

但我想它们现在都是一样的,没有前缀。 [3] 解决方案已经很老了,从那时起世界已经发生了很大变化。

可悲的是,浏览器支持至少在 2019 年 [4] 是相同的,也许现在也是。

来源:

[3]jQuery / HTML5 / gwt app for WP8 (Lumia 920) device: vertical css scroll fix

[4]https://css-tricks.com/almanac/properties/t/touch-action/

【讨论】:

  • 我很难过听到这个问题需要如此臃肿的解决方案,但感谢有人真正解决了这个问题。移动 javascript 开发人员应该在街上暴动。如果有更标准的解决方案可用,我希望您(或其他人)会更新此答案。感谢您的帮助。
  • 我得看看。也许可以找到一个 android + windows 解决方案来缓解这一点。
【解决方案2】:

问题

在全屏画布元素顶部显示一个 div,拦截元素画布上的正常点击事件。

解决方案

除了点击事件,还需要引入以下触摸事件:

  • 触摸开始
  • 触摸结束
  • 触摸移动
  • 触摸取消

附加信息

您只能在画布事件中使用preventDefault,因此您仍然应该能够在画布中创建一个可点击/可触摸元素,该元素显示画布外部的 div,通过设置z-index 高于画布元素987654324@ 在 div 上。 div 还应该有100vh100vw 分别设置敌人的宽度和高度,并且是position: fixed。 div 还应该有一个按钮可以再次隐藏display: none

参考文献

https://stackoverflow.com/a/51127296/806876

【讨论】:

  • 我在上面添加了一些示例代码。我不确定您所说的“全屏弹出”是什么意思。我确实编辑了画布的宽度/高度,以在窗口调整大小时完美匹配屏幕的视口。我的情况是我有一个网页,它只包含一个整页画布。为了允许在该画布上进行交互,我必须在 touchstart 上设置 evt.preventDefault(否则,移动浏览器将允许用户轻推页面内容)。这不允许点击事件。除了单击事件之外,我无法从任何内容启动页面。没有弹出窗口、弹出窗口等...
  • @Phildo 感谢您的澄清。我已经更新了我的答案。您已经在拦截 click 和 touchstart,正在发生滚动,因为您从未拦截过 touchmove。我还解释了如果您想要在画布上方添加一个 div 叠加层(即“popunder”)该怎么做,我假设您想要“启动网页”按钮 - 否则我可以在附加信息下删除该说明。
  • 您所说的问题不是我感兴趣的问题,也不是我所说的问题,也不是示例代码中说明的问题。我将编辑我的上述问题以更清楚。
猜你喜欢
相关资源
最近更新 更多
热门标签