Обнаружение двойного касания на вершине приложения в мобильном 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.