Обнаружение двойного касания на вершине приложения в мобильном Safari с помощью JavaScript

iOS имеет соглашение о том, что двойное нажатие на верхней панели (то есть, где отображается текущее время) прокручивает приложение в верхнее состояние. Например, двойное нажатие верхней панели в Safari приводит вас к верхней части текущей веб-страницы, а двойное нажатие на верх в Facebook/Twitter приводит вас к началу фида. Это очень полезный ярлык для навигации.

Позвольте называть его TopTap для целей этого вопроса.

Мне интересно, как я могу обнаружить TopTaps в приложении JavaScript в мобильном Safari, то есть не в приложении iOS, а на веб-странице, которая, как представляется, просматривается в мобильном Safari.

В моем конкретном случае я не могу полагаться на встроенное поведение Mobile Safari TopTap, потому что мой документ состоит из одного элемента <canvas>, который реализует свой собственный прокручиваемый интерфейс. Я хочу, чтобы иметь возможность обнаруживать TopTap, чтобы я мог прокрутить этот <canvas> в его верхнее состояние.

Я экспериментировал с добавлением обработчика событий onscroll, но в этом событии нет никакой различающейся информации, которая позволила бы мне изолировать TopTaps. Кроме того, я не могу использовать события касания (touchstart и т.д.), Потому что TopTap происходит в Chrome браузера/ОС, за пределами веб-страницы.

Любые идеи?

Ответ 1

Как оказалось, двойное нажатие на собственную строку состояния вызовет событие прокрутки на document.body, которое вы действительно можете прослушать. Трюк, как вы упомянули, как вы можете определить, если он из двойного нажатия или нет?

Чтобы обнаружить это, тело должно быть прокручено вниз для начала. И установка положения прокрутки вызывает событие прокрутки.

Пока это куча хаков, мне удалось добиться этого:

Код: https://github.com/HenrikJoreteg/holy-grail-ios-layout

Демо: http://ios-layout.surge.sh

В принципе, вы не используете <body> как контейнер. Вы устанавливаете его как position: absolute и полную высоту/ширину. Затем у вас есть какой-то контейнерный элемент, который вы установили в position: fixed, который вы используете в качестве своего фактического контейнера для вашего контента.

Выполнение этого позволяет программно прокручивать тело, не затрагивая ничего визуального на странице.

Теперь вы настроены на прослушивание событий прокрутки на теле, и в идеале пользователь не может фактически вызвать прокрутку на теле, кроме как дважды нажав на строку состояния.

К сожалению, вам нужно делать всевозможные глупые вещи, чтобы сделать эту работу.

  • Поместите что-то выше, чем 100% в тело, чтобы тело действительно могло что-то прокрутить.
  • Программно установить положение прокрутки в 1 для запуска и после двойного нажатия каждой строки состояния.
  • Установите обработчик отклоненного прокрутки на теле, который срабатывает только в том случае, если он знает, что это событие не вызвано установкой позиции 1.
  • Как выясняется, iOS также любит разрывать вещи при повороте телефона и т.д.
  • Используйте следующий CSS, чтобы содержимое ваших контейнеров содержимого было прокручиваемым с импульсом и резиновым диапазоном:

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

Во всяком случае, это что-то:)

Дополнительная информация в реестре github, но в любом случае это действительно хорошо работает для iOS 8 (не тестировали другие версии iOS).

Ответ 2

Если ваша цель - недавняя iOS, вы можете поместить элемент поверх вашего canvas, который position: fixed, в верхнюю часть окна просмотра, и использовать его для обнаружения двойных нажатий.

РЕДАКТИРОВАТЬ: Я думал о чем-то вроде ниже, но, как указывает Адриан, ему нужно, чтобы это произошло, когда родной браузер хром был также двойным нажатием.

<!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>

Ответ 3

Можно ли создать скрытый собственный элемент html, ту же высоту, что и содержимое вашего холста. Затем сопоставьте положение прокрутки на нативном элементе в том же положении внутри холста. Также можно скрыть виджет прокрутки холста.

Таким образом, насколько это касается пользователей, они видят только встроенную полосу прокрутки... но все события прокрутки отображаются на холсте, в том числе на панели состояния.

Может не работать, если у вас есть другой HTML-контент на странице, но может быть, если видится только холст.

Изменить: здесь очень грубый прототип http://jsbin.com/cisizopi/3

Я имитирую холст и его содержимое с помощью divs

Ответ 4

После небольшого исследования я наткнулся на это сообщение: http://prud.github.io/ios-overflow-scroll-to-top/. Я не уверен, что это сделает то, что вы ищете. Кроме того, я вполне уверен, что вы не можете перехватить связь состояния с JS в браузере для IOS.