【问题标题】:Detecting doubletap on app top in mobile Safari via JavaScript通过 JavaScript 在移动 Safari 中检测应用程序顶部的双击
【发布时间】:2014-03-05 16:25:54
【问题描述】:

iOS 有一个约定,双击顶部栏(即显示当前时间的位置)会将应用滚动到顶部状态。例如,在 Safari 中双击顶部栏会将您带到当前网页的顶部,而在 Facebook/Twitter 中双击顶部会将您带到提要的顶部。这是一个非常有用的导航快捷方式。

为了这个问题,我们称它为 TopTap。

我想知道如何在移动 Safari 的 JavaScript 应用中检测 TopTaps —— 也就是说,不是在 iOS 应用中,而是在碰巧在移动 Safari 中查看的网页中。

在我的特殊情况下,我不能依赖内置的移动 Safari TopTap 行为,因为我的文档由一个实现其自己的可滚动界面的 <canvas> 元素组成。我希望能够检测到 TopTap,以便我可以将 <canvas> 滚动到其顶部状态。

我已经尝试添加一个onscroll 事件处理程序,但该事件中没有可区分的信息可以让我隔离 TopTaps。另外,我不能使用触摸事件(touchstart 等),因为 TopTap 发生在浏览器/OS chrome 中,不在网页范围内。

有什么想法吗?

【问题讨论】:

    标签: javascript html ios safari


    【解决方案1】:

    事实证明,双击本机​​状态栏将触发document.body 上的滚动事件,您可以实际上监听该事件。正如您所提到的,技巧是,您如何确定它是否来自双击?

    为了检测它,身体必须向下滚动才能开始。并且设置滚动位置会引发滚动事件。

    虽然这是一堆黑客,但我已经能够让这个工作:

    代码:https://github.com/HenrikJoreteg/holy-grail-ios-layout

    演示:http://ios-layout.surge.sh

    基本上,您并没有真正将<body> 用作容器。您将其设置为position: absolute 和全高/全宽。然后,您将某种容器元素设置为 position: fixed,用作内容的实际容器。

    这样做可以让您以编程方式滚动正文,而不会影响页面上的任何视觉效果。

    现在您已设置为监听 body 上的滚动事件,理想情况下,用户实际上不能通过双击状态栏在 body 上引起滚动。

    不幸的是,您必须做各种愚蠢的事情才能完成这项工作。

    1. 在 body 中放置比 100% 更高的东西,这样 body 就可以滚动。
    2. 以编程方式将滚动位置设置为 1 以启动和在每个状态栏双击之后。
    3. 在主体上设置一个去抖滚动处理程序,仅当它知道事件不是由将位置设置为 1 引起时才会触发。
    4. 事实证明,iOS 也喜欢在您旋转手机等时破坏东西。
    5. 使用以下 CSS 使您的实际内容容器的内容可通过动量和橡皮筋滚动:

    overflow-y: scroll; /* has to be scroll, not auto */ -webkit-overflow-scrolling: touch;

    无论如何,它是一些东西:)

    更多信息在 github repo 中,但无论如何,这似乎确实适用于 iOS 8(尚未测试其他版本的 iOS)。

    【讨论】:

    • 在 iOS9 中,对于以“独立”模式运行的应用程序来说,这似乎是 Just Work™。但至少在初始版本中,状态栏颜色和启动图像似乎不起作用。
    【解决方案2】:

    如果您的目标是最近的 iOS,您可以在 canvas 上放置一个元素 position: fixed 到视口的顶部,并使用它来检测双击。

    编辑:我在想类似下面的事情,但正如 Adrian 指出的那样,当本地浏览器 chrome 也被双击时,他需要它发生。

    <!doctype html>
    <html>
        <head>
            <style type="text/css">
            canvas {
                height: 1000px;
                width: 320px;
            }
            #top-tap {
                height: 16px;
                left: 0;
                position: fixed;
                right: 0;
                top: 0;
            }
            </style>
        </head>
        <body>
            <canvas></canvas>
            <a id="top-tap"></a>
            <script type="text/javascript">
            function secondTap() {
                window.scrollTo(0,0)
            }
            document.querySelector('#top-tap').addEventListener('touchend', function (e) {
                var self = this
                this.addEventListener('touchend', secondTap)
                setTimeout(function () {
                    self.removeEventListner('touchend', secondTap)
                }, 100)
            })
            </script>
        </body>
    </html>
    

    【讨论】:

    • 有趣——我想如果双击发生在操作系统时间栏/浏览器铬(文档外)上,这将不起作用。
    • 啊,真的。在这种情况下,您可能需要一个原生包装器(例如 PhoneGap)来与您的页面对话。
    【解决方案3】:

    是否可以创建一个隐藏的原生 html 元素,与画布中的内容高度相同。然后将原生元素上的滚动位置映射到画布内的相同位置。也可以隐藏画布滚动小部件。

    因此,就用户而言,他们只看到本机滚动条......但所有滚动事件都映射到画布 - 包括状态栏点击。

    如果页面上有其他 HTML 内容可能无法使用,但如果只有画布可见则可能。

    编辑:这是一个非常粗糙的原型http://jsbin.com/cisizopi/3

    我正在模拟一个画布,它的内容是带有 div 的

    【讨论】:

      【解决方案4】:

      在做了一些研究之后,我发现了这个帖子:http://prud.github.io/ios-overflow-scroll-to-top/。我不确定这是否会满足您的需求。另外,我很确定你不能在IOS浏览器中拦截状态栏触摸。

      【讨论】:

      • 在链接文章的底部,他确实指出:如果您正在为 Mobile Safari 构建 Web 应用程序,则无法监听状态栏上的事件。但是,如果您使用的是 UIWebView,您实际上可以使用一些本机代码来实现这一点。阅读有关如何检测状态栏触摸的 StackOverflow 问题 (stackoverflow.com/questions/3753097/…)
      猜你喜欢
      • 2012-05-03
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      • 2014-05-25
      • 1970-01-01
      • 2011-05-24
      • 1970-01-01
      相关资源
      最近更新 更多