Отключить масштабирование окна просмотра iOS 10+ safari?
Я обновил свой iPhone 6 plus до iOS 10 бета-версии и только что обнаружил, что в мобильном сафари вы можете масштабировать любые веб-страницы, дважды нажав или нажав IGNORE, user-scalable=no
код в метатеге. Я не знаю, это ошибка или особенность. Если это рассматривается как функция, как отключить масштабирование окна просмотра в iOS 10 Safari?
обновленный выпуск iOS 11/12, iOS 11 и iOS 12 по-прежнему НЕ УВАЖАЮТ user-scalable=no
метатег.
20 ответов
В iOS 10 можно предотвратить масштабирование веб-страниц, но с вашей стороны это потребует дополнительных усилий. Я предполагаю, что аргумент состоит в том, что степень сложности должна помешать разработчикам Cargo-Cult опускать "user-scalable = no" в каждый тег окна просмотра и создавать ненужные трудности для пользователей с нарушениями зрения.
Тем не менее, я бы хотел, чтобы Apple изменила свою реализацию так, чтобы существовал простой (метатег) способ отключения двойного нажатия для увеличения. Большая часть трудностей связана с этим взаимодействием.
Вы можете остановить масштабирование с помощью чего-то вроде этого:
document.addEventListener('touchmove', function (event) {
if (event.scale !== 1) { event.preventDefault(); }
}, false);
Обратите внимание, что если какие-либо более глубокие цели вызывают stopPropagation для события, событие не достигнет документа, и этот слушатель не предотвратит поведение масштабирования.
Отключение двойного касания для увеличения аналогично. Вы отключаете любое нажатие на документ, происходящее в течение 300 миллисекунд после предыдущего нажатия:
var lastTouchEnd = 0;
document.addEventListener('touchend', function (event) {
var now = (new Date()).getTime();
if (now - lastTouchEnd <= 300) {
event.preventDefault();
}
lastTouchEnd = now;
}, false);
Если вы неправильно настроите элементы формы, при фокусировке на входе произойдет автоматическое масштабирование, а поскольку вы в основном отключили ручное масштабирование, теперь его практически невозможно уменьшить. Убедитесь, что размер входного шрифта>= 16px.
Если вы пытаетесь решить эту проблему в WKWebView в нативном приложении, приведенное выше решение является жизнеспособным, но это лучшее решение: /questions/21415844/otklyuchit-zhest-uvelicheniya-v-wkwebview/21415877#21415877. И, как упоминалось в других ответах, в iOS 10 beta 6 Apple теперь предоставила флаг для соблюдения метатега.
Обновление, май 2017 года: я заменил старый метод проверки длины касания на отключение при нажатии на более простой подход "check event.scale on touchmove". Должно быть более надежным для всех.
Это новая функция в iOS 10.
Из примечаний к выпуску iOS 10 beta 1:
- Чтобы улучшить доступность веб-сайтов в Safari, пользователи теперь могут увеличивать масштаб, даже если веб-сайт настроен.
user-scalable=no
в окне просмотра.
Я ожидаю, что мы скоро увидим дополнение JS, чтобы каким-то образом отключить это.
Я смог это исправить используя touch-action
Свойство css для отдельных элементов. Попробуйте установить touch-action: manipulation;
на элементы, на которые обычно нажимают, такие как ссылки или кнопки.
Обходной путь, который работает в Mobile Safari на данный момент, состоит в том, чтобы использовать третий аргумент в adddEventListener
быть { passive: false }
Таким образом, полный обход выглядит так:
document.addEventListener('touchmove', function (event) {
if (event.scale !== 1) { event.preventDefault(); }
}, { passive: false });
Вы можете проверить, поддерживаются ли опции, чтобы оставаться обратно совместимыми.
Используйте «touch-action: pan-x pan-y», чтобы отключить «масштабирование щипком», а также «масштабирование двойным касанием». Он работает на всех сенсорных экранах / телефонах, которые я тестировал, включая iOS Safari 14.5.1.
Похоже, что это поведение предположительно изменилось в последней бета-версии, которая на момент написания статьи была бета 6.
Из заметок о выпуске iOS 10 Beta 6:
WKWebView
теперь по умолчанию уважатьuser-scalable=no
из окна просмотра. КлиентыWKWebView
может улучшить доступность и позволить пользователям увеличивать масштаб на всех страницах, устанавливаяWKWebViewConfiguration
имуществоignoresViewportScaleLimits
вYES
,
Однако в моем (очень ограниченном) тестировании я пока не могу подтвердить, что это так.
Редактировать: проверено, iOS 10 Beta 6 с уважением user-scalable=no
по умолчанию для меня.
Я потратил около часа в поисках более надежного варианта javascript и не нашел его. Так уж сложилось, что в последние несколько дней я возился с hammer.js (Hammer.js - это библиотека, которая позволяет легко манипулировать всеми видами сенсорных событий), и в большинстве случаев терпел неудачу в том, что я пытался сделать.
С этим предупреждением и пониманием, что я ни в коем случае не эксперт по javascript, я пришел к решению, которое в основном использует hammer.js для захвата событий пинч-зума и двойного касания, а затем регистрирует и отбрасывает их.
Убедитесь, что вы включили hammer.js на свою страницу, а затем попробуйте вставить этот javascript где-нибудь в голове:
< script type = "text/javascript" src="http://hammerjs.github.io/dist/hammer.min.js"> < /script >
< script type = "text/javascript" >
// SPORK - block pinch-zoom to force use of tooltip zoom
$(document).ready(function() {
// the element you want to attach to, probably a wrapper for the page
var myElement = document.getElementById('yourwrapperelement');
// create a new hammer object, setting "touchAction" ensures the user can still scroll/pan
var hammertime = new Hammer(myElement, {
prevent_default: false,
touchAction: "pan"
});
// pinch is not enabled by default in hammer
hammertime.get('pinch').set({
enable: true
});
// name the events you want to capture, then call some function if you want and most importantly, add the preventDefault to block the normal pinch action
hammertime.on('pinch pinchend pinchstart doubletap', function(e) {
console.log('captured event:', e.type);
e.preventDefault();
})
});
</script>
В моем конкретном случае я использую Babylon.js для создания 3D-сцены, и вся моя страница состоит из одного полноэкранного холста. 3D-движок имеет свою собственную функцию масштабирования, но в iOS вмешивается масштабирование. Я обновил ответ @Joseph, чтобы преодолеть мою проблему. Чтобы отключить его, я понял, что мне нужно передать {passive: false} в качестве опции слушателю событий. У меня работает следующий код:
window.addEventListener(
"touchmove",
function(event) {
if (event.scale !== 1) {
event.preventDefault();
}
},
{ passive: false }
);
Мы можем получить все, что хотим, вставив одно правило стиля и перехватывая события масштабирования:
$(function () {
if (!(/iPad|iPhone|iPod/.test(navigator.userAgent))) return
$(document.head).append(
'<style>*{cursor:pointer;-webkit-tap-highlight-color:rgba(0,0,0,0)}</style>'
)
$(window).on('gesturestart touchmove', function (evt) {
if (evt.originalEvent.scale !== 1) {
evt.originalEvent.preventDefault()
document.body.style.transform = 'scale(1)'
}
})
})
✔ Отключить масштабирование.
✔ Отключение двойного увеличения.
✔ Прокрутка не влияет.
✔ Отключает выделение касанием (которое запускается в iOS по правилу стиля).
ВНИМАНИЕ: настройте iOS-обнаружение по своему вкусу. Подробнее об этом здесь.
Приносим извинения Люкьяксону и Петру Ковальски, чьи ответы представлены в измененном виде в приведенном выше коде.
Проверьте масштабный коэффициент в событии касания, затем предотвратите событие касания.
document.addEventListener('touchmove', function(event) {
event = event.originalEvent || event;
if(event.scale > 1) {
event.preventDefault();
}
}, false);
Я попробовал предыдущий ответ о пинч-зум
document.documentElement.addEventListener('touchstart', function (event) {
if (event.touches.length > 1) {
event.preventDefault();
}
}, false);
однако иногда экран продолжает увеличиваться, когда event.touches.length > 1. Я обнаружил, что лучший способ - использовать событие touchmove, чтобы избежать движения пальца по экрану. Код будет примерно таким:
document.documentElement.addEventListener('touchmove', function (event) {
event.preventDefault();
}, false);
Надеюсь, это поможет.
Я придумал довольно наивное решение, но, похоже, оно работает. Моей целью было не допустить, чтобы случайные двойные касания интерпретировались как увеличение, сохраняя при этом увеличение масштаба для обеспечения доступности.
Идея заключается в измерении времени между первым touchstart
и второй touchend
в двойном нажатии, а затем интерпретировать последний touchend
нажмите, если задержка слишком мала. Несмотря на предотвращение случайного масштабирования, кажется, что этот метод не влияет на прокрутку списка, что приятно. Не уверен, что я ничего не пропустил, хотя.
let preLastTouchStartAt = 0;
let lastTouchStartAt = 0;
const delay = 500;
document.addEventListener('touchstart', () => {
preLastTouchStartAt = lastTouchStartAt;
lastTouchStartAt = +new Date();
});
document.addEventListener('touchend', (event) => {
const touchEndAt = +new Date();
if (touchEndAt - preLastTouchStartAt < delay) {
event.preventDefault();
event.target.click();
}
});
Вдохновленный суть от mutewinter и ответ Джозефа.
По запросу я перевел свой комментарий на ответ, чтобы люди могли проголосовать за него:
Это работает в 90% случаев для iOS 13:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=no, shrink-to-fit=no" />
а также
<meta name="HandheldFriendly" content="true">
Непреднамеренное масштабирование имеет место, когда:
- Пользователь дважды нажимает на компонент интерфейса
- Пользователь взаимодействует с окном просмотра, используя две или более цифры (пинч)
Чтобы предотвратить поведение двойного нажатия, я нашел два очень простых обходных пути:
<button onclick='event.preventDefault()'>Prevent Default</button>
<button style='touch-action: manipulation'>Touch Action Manipulation</button>
Оба этих параметра не позволяют Safari (iOS 10.3.2) увеличить масштаб кнопки. Как видите, один - только JavaScript, другой - только CSS. Используйте соответственно.
Вот демоверсия: https://codepen.io/lukejacksonn/pen/QMELXQ
Я не пытался предотвратить поведение прижима (пока), в первую очередь потому, что я склонен не создавать мультисенсорные интерфейсы для Интернета, а во-вторых, я пришел к мысли, что, возможно, все интерфейсы, включая собственный интерфейс приложения, должны быть "ущипнуть, чтобы увеличить"-можно в местах. Я бы по-прежнему старался избегать необходимости делать это пользователем, чтобы сделать ваш пользовательский интерфейс доступным для них любой ценой.
Как бы странно это ни звучало, по крайней мере для Safari в iOS 10.2, двойное нажатие для масштабирования магически отключено, если у вашего элемента или любого из его предков есть одно из следующего:
- Слушатель onClick - это может быть простой noop.
cursor: pointer
установить в CSS
Нашел эту простую работу, которая, кажется, предотвращает двойной щелчок для увеличения
// Convert touchend events to click events to work around an IOS 10 feature which prevents
// developers from using disabling double click touch zoom (which we don't want).
document.addEventListener('touchend', function (event) {
event.preventDefault();
$(event.target).trigger('click');
}, false);
В текущей версии сафари это больше не работает. Вы должны определить второй параметр как непассивный, передав {passiv:false}
document.addEventListener('touchmove', function(e) {
e.preventDefault();
}, { passive: false });
Если ничего из вышеперечисленного не работает для вас, просто установка размера шрифта в поле на 16px решит проблему.
Я проверил все вышеупомянутые ответы на практике со своей страницей на iOS (iPhone 6, iOS 10.0.2), но безуспешно. Это мое рабочее решение:
$(window).bind('gesturestart touchmove', function(event) {
event = event.originalEvent || event;
if (event.scale !== 1) {
event.preventDefault();
document.body.style.transform = 'scale(1)'
}
});
Это сработало для меня:
document.documentElement.addEventListener('touchmove', function (event) {
event.preventDefault();
}, false);