Отключить масштабирование видового экрана iOS 10+?

Я обновил свой iPhone 6 plus до бета-версии iOS 10 и только что обнаружил, что в мобильном сафари можно масштабировать любые веб-страницы, дважды нажав или нажав IGNORE, user-scalable=no кода в метатеге. Я не знаю, это ошибка или особенность. Если это рассматривается как функция, как мы можем отключить масштабирование окна просмотра iOS 10 Safari?


обновленный выпуск iOS 11/12, iOS 11 и iOS 12 по-прежнему НЕ уважают user-scalable=no метатега.

mobile github site on Safari

Ответ 1

Можно было предотвратить масштабирование веб-страниц в сафари на 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 в нативном приложении, приведенное выше решение является жизнеспособным, но это лучшее решение: fooobar.com/questions/29677/.... И, как упоминалось в других ответах, в iOS 10 beta 6 Apple теперь предоставила флаг для соблюдения метатега.

Обновление, май 2017 года: я заменил старый метод проверки длины касания на отключение при нажатии на более простой подход "check event.scale on touchmove". Должно быть более надежным для всех.

Ответ 2

Это новая функция в iOS 10.

Из примечаний к выпуску iOS 10 beta 1:

  • Чтобы улучшить доступность веб-сайтов в Safari, пользователи теперь могут сжимать до масштабирования, даже если веб-сайт устанавливает user-scalable=no в окне просмотра.

Я ожидаю, что мы скоро увидим дополнение JS, чтобы каким-то образом отключить его.

Ответ 3

Похоже, что это поведение якобы было изменено в последней бета-версии, которая на момент написания была бета-версии 6.

Из примечаний к выпуску для iOS 10 Beta 6:

WKWebView теперь по умолчанию соблюдает user-scalable=no из окна просмотра. Клиенты WKWebView могут улучшить доступность и позволить пользователям сжимать на все страницы, установив WKWebViewConfigurationсвойство ignoresViewportScaleLimits до YES.

Однако в моем (очень ограниченном) тестировании я пока не могу подтвердить это.

Изменить: подтверждено, iOS 10 Beta 6 respects user-scalable=no по умолчанию для меня.

Ответ 4

Я смог исправить это, используя свойство touch-action css для отдельных элементов. Попробуйте установить touch-action: manipulation; на элементы, которые обычно нажимаются, например, ссылки или кнопки.

Ответ 5

Я потратил около часа на поиск более надежного варианта 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>

Ответ 6

Проверить масштабный коэффициент в событии touchove, а затем предотвратить событие касания.

document.addEventListener('touchmove', function(event) {
    event = event.originalEvent || event;
    if(event.scale > 1) {
        event.preventDefault();
    }
}, false);

Ответ 7

Я попробовал предыдущий ответ о масштабировании

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);

Надеюсь, это поможет.

Ответ 8

Я придумал довольно наивное решение, но, похоже, оно работает. Моя цель состояла в том, чтобы предотвратить случайное двойное касание, которое будет интерпретироваться как увеличение, сохраняя при этом увеличение масштаба для обеспечения доступности.

Идея состоит в том, чтобы измерить время между первым 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 и Джозеф ответ.

Ответ 9

Мы можем получить все, что хотим, введя одно правило стиля и перехватывая события масштабирования:

$(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-обнаружение по своему вкусу. Подробнее об этом здесь.


Извините lukejackson и Петр Ковальски, ответы которого отображаются в модифицированном виде в коде выше.

Ответ 10

Обходной путь, который работает в Mobile Safari на момент написания статьи, заключается в том, чтобы третий аргумент в addEventListener был { passive: false }, поэтому полный обходной путь выглядит следующим образом:

document.addEventListener('touchmove', function (event) {
  if (event.scale !== 1) { event.preventDefault(); }
}, { passive: false });

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

Ответ 11

В моем конкретном случае я использую Babylon.js для создания 3D-сцены, и вся моя страница состоит из одного полноэкранного холста. 3D-движок имеет свою собственную функцию масштабирования, но в iOS вмешивается масштабирование. Я обновил ответ @Joseph, чтобы преодолеть мою проблему. Чтобы отключить его, я понял, что мне нужно передать {passive: false} в качестве опции слушателю событий. У меня работает следующий код:

window.addEventListener(
    "touchmove",
    function(event) {
        if (event.scale !== 1) {
            event.preventDefault();
        }
    },
    { passive: false }
);

Ответ 12

Как ни странно, по крайней мере для Safari в iOS 10.2, двойное нажатие для увеличения волшебным образом отключается, если ваш элемент или любой из его предков имеет одно из следующих значений:

  • Слушатель onClick - это может быть простой noop.
  • A cursor: pointer в CSS

Ответ 13

Непреднамеренное масштабирование имеет тенденцию возникать, когда:

  • Пользовательские двойные нажатия на компонент интерфейса
  • Пользователь взаимодействует с окном просмотра с использованием двух или более цифр (пинч)

Чтобы предотвратить поведение двойного крана, я обнаружил два очень простых обходных решения:

<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

Я не пытался предотвратить поведение пинча (пока), прежде всего потому, что я стараюсь не создавать мультитач-интерфейсы для Интернета, а во-вторых, я пришел к идее, что, возможно, все интерфейсы, включая собственный пользовательский интерфейс приложения, должны быть "щепоткой" для увеличения "в местах. Я бы все же проектировал, чтобы пользователь не делал этого, чтобы сделать свой пользовательский интерфейс доступным для них любой ценой.

Ответ 14

Нашел эту простую работу, которая, как представляется, предотвращает двойной щелчок для увеличения:

    // 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);

Ответ 15

Я проверил все вышеперечисленные ответы на практике с моей страницей на 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)'
    }
});

Ответ 16

это сработало для меня:

document.documentElement.addEventListener('touchmove', function (event) {
    event.preventDefault();
}, false);

Ответ 17

Если ничего из вышеперечисленного не работает для вас, просто установка размера шрифта в поле на 16px решит проблему.