отключить масштабирование окна просмотра iOS 10+ safari?

164

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


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

мобильный сайт GitHub на Safari

Сэм Су
источник
2
Особенность доступности: В Safari на iOS 10
стоит
87
Нет, это не так. Это плохая практика для обычного веб-контента. Для веб-приложений поведение масштабирования по умолчанию может полностью испортить удобство использования. Например, никто не хочет увеличивать кнопку канала вверх, потому что они дважды нажимали на нее, и не увеличивать часть видеоигры, потому что они дважды нажимали кнопку перехода. Есть причина, по которой эта функция была добавлена ​​в первую очередь, и нет смысла нарушать юзабилити для всех только потому, что несколько «веб-дизайнеров» не знают, что они делают. Иди и кричи на дизайнеров сайта и прекрати ломать браузер.
17
36
Сказать, что это «плохая практика», - это мнение, и это не меняет того факта, что Apple настаивает на использовании веб-стандартов, которые сообщество тратит месяцы / годы / десятилетия на внедрение кросс-платформенных и гигантских дерьмов. Почему Apple должна диктовать, что веб-дизайнеры не знают, что они делают? Страшный аргумент.
Самрап
2
Лично я думаю, что это происходит из стандартного кода онлайн, где разработчики просто копируют и вставляют вслепую, не зная, какова цель кода.
Уильям
7
Ответ прост, Apple: сделайте отключение метатега настройкой доступности по умолчанию. Те, кому это нужно, получат это, не наказывая тех, кто этого не делает.
Рубен Мартинес-младший

Ответы:

94

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

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

Джозеф
источник
3
Обратите внимание, что взлом сенсорного старта непоследователен ... и если вам удастся обойти его, вы застрянете в очень неудобном состоянии
Сэм Саффрон
5
Например. полноэкранные картографические приложения, есть функция масштабирования, жестко запрограммированная в картографическом приложении (Google Maps JS, Leaflet и т. д.). Google советует добавить метатег, <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />и если браузер не учитывает метатег, это очень плохой дизайн браузера. Другой, как и очень плохой дизайн, это сдвиг назад / вперед, что невозможно предотвратить в iOS 9/10. Это сильно нарушает перетаскивание действий внутри веб-приложения.
Тимо Кяхконен
4
Если пользователь начнет перетаскивать его одним пальцем, тогда второй палец на экране сможет масштабировать. Вы можете отключить и масштабирования и прокрутки с preventDefaultON touchmove. Вы не можете (полностью) отключить масштабирование без отключения прокрутки.
Паоло
10
Вау, эта часть (я вставлю сюда) была СУПЕР полезна для меня. Я не видел, чтобы кто-нибудь еще упоминал об этом в Интернете. Мне потребовались часы, чтобы решить эту проблему. Я очень разочарован выбором дизайна UX от Apple по этому поводу, где формируется автоматическое увеличение, но затем не уменьшение масштаба. If you don't set up your form elements right, focusing on an input will auto-zoom, and since you have mostly disabled manual zoom, it will now be almost impossible to unzoom. Make sure the input font size is >= 16px.
Райан
6
Кажется, что это больше не работает в iOS 12. Есть идеи, как заставить это работать на iOS 12?
TJR
78

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

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

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

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

Пол Херартс
источник
4
@ Онза: Я не думаю, что это плохо. Я думаю это хорошо. Отключение пинч / масштабирование (поведение пользователя по умолчанию) считается плохим, и многие мобильные сайты делают это. Единственный приемлемый случай пользователя - это настоящее веб-приложение, которое выглядит и ощущается как приложение.
wouterds
6
Плохо ... Я меняю видовой экран с помощью js и блокирую масштаб только тогда, когда некоторые элементы выбраны на веб-сайте, теперь он нарушается из-за этого "решения". Если кто-то решит заблокировать это - есть причина.
Женя
9
@Karlth, это очень кровать для разработчика игр
Sandeep
14
У меня есть IOS 10.0.2, масштабируемый пользователем = нет, больше не отключает масштабирование на нашем веб-сайте ... Наша основная проблема с масштабированием связана с нашим фиксированным боковым меню. Это просто нарушает макет. Есть идеи или решения по этому поводу? Я понимаю, что масштабирование хорошо для доступности, мы сделали масштабирование доступным для определенных частей нашего сайта, используя js events (hammer) и css. Я не понимаю, почему правило должно быть наложено на всех, похоже, что PC Police начинает захватить и наш мир разработчиков ?!
Webkit
50
«Единственный приемлемый случай пользователя - это настоящее веб-приложение, которое выглядит и ощущается как приложение». - и это, как вы сказали, реальный, приемлемый вариант использования, то есть не что редкость ..
Флори
21

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

iainbeeston
источник
1
«Манипулирование» не предотвращает масштабирование, только двойное нажатие.
Моос
4
Это должен быть принятый ответ. Вы можете использовать touch-action: none;для управления всеми жестами самостоятельно.
Гай
4
это здорово - отключение масштабирования двойным касанием, а масштабирование щепоткой, что СЛЕДУЕТ считать жестом - двойное нажатие не должно. 1 собака - это собака. 1 собака + 1 собака не делает космический челнок. Это делает 2 собаки, и они делают то, что вы ожидаете от 2 собак. Я никогда не ожидал, что 2 собаки будут космическим челноком. Никогда.
Ларри
5
@GuySopher iOS не предоставляет touch-action: noneтолько manipulatoin, что оставляет проблему масштабирования пинч как есть.
человечество и
14

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

Из заметок о выпуске iOS 10 Beta 6:

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

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

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

Cellane
источник
11
10.0.1 здесь. Не уважает это. Что с Apple избавляется от функций, которые нужны всем ...
lifwanian
1
Это относится WKWebView не к сафари. Источник: Одно из наших картографических приложений сломалось, и мы не знаем, как это исправить.
Фабио Полони,
Ага! Извиняюсь, я пришел сюда, когда искал решение для той же самой ошибки / функции WKWebViewи предположил, что первоначальный вопрос задавался WKWebViewпри написании моего ответа. Поэтому я предполагаю, что во время одной из первых бета-версий Apple изменила поведение обоих WKWebViewи мобильного Safari, затем в бета-6 они изменили поведение, WKWebViewно сохранили его для мобильного Safari.
Cellane
1
10.0.2 не уважает user-scalable=no. Я не уверен, почему они когда-либо отменят это, только чтобы вернуть это, только чтобы удалить это снова.
Эйдан Хакимян
13

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

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

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

Каспер Фабрициус
источник
3
Кто-нибудь пробовал это на iOS 12? Я добавил приведенный выше код, и он ничего не делает для моего веб-приложения. Все еще в состоянии увеличить этот тупой Safari. Моя мета - тег окна просмотра выглядит следующим образом : кстати <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">.
Патрик ДаВейдер
2
@PatrickDaVader Да, не могу найти никакого рабочего решения для iOS 12 Safari. Становится морской болезнью от непрерывного масштабирования.
Джейми Берч
1
Этот работает в iOS 13. Мои теги <meta> включают в себя: <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">
Sterling Bourne
1
@SterlingBourne Скопировал ваши настройки. Работает, но только в 90% случаев. Не уверен, почему не все время.
Hillcow
1
Ответ @SterlingBourne работал на меня! Спасибо. Он должен публиковать его как ответ, а не как комментарий, чтобы за него проголосовали <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 ">
Джин Блэк,
8

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

sporker
источник
Я также пытался решить эту проблему при работе с hammer.js и могу подтвердить, что могу предотвратить масштабирование области просмотра, добавив a .preventDefaultко всем обработчикам жестов молотка. Я использую swipe / pinch / pan / tap вместе, я добавил его ко всем обработчикам, я не знаю, есть ли конкретный, который выполняет эту работу.
Конан
6

Я попробовал предыдущий ответ о пинч-зум

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

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

Chihying Wu
источник
7
Это работает только в том случае, если ваше приложение идеально подходит ... если у вас есть прокручиваемый контент, оно не работает ... все равно неплохой взлом для некоторых сценариев.
eljamz
8
Это даже отключает прокрутку на сайте .. ПЛОХО
Gags
@eljamz спасибо, что сообщили мне, и да .. мое приложение идеально подходит для экрана.
Chihying Wu
@ Gags Я еще не тестировал функцию прокрутки, спасибо, что сообщили мне.
Chihying Wu
6

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

document.addEventListener('touchmove', function(event) {
    event = event.originalEvent || event;
    if(event.scale > 1) {
        event.preventDefault();
    }
}, false);
Parmod
источник
2
iOS 13 меняет значение false на {passive: false}
wayofthefuture
6

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

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


Приносим извинения Люкьяксону и Петру Ковальски , чьи ответы представлены в измененном виде в приведенном выше коде.

jeff_mcmahan
источник
Это работает на моем эмуляторе iPad под iOS 11.2. На моем реальном iPad под управлением iOS 11.3 это не работает. Я добавил console.log, чтобы убедиться, что события запускаются и отображаются в консоли. Это как то связано с iOS 11.3? Или с реальными устройствами?
Матье Р.
1
@MathieuR. Это проблема iOS 11.3. Это можно исправить, используя один из addEventListenerоснованных ответов и передавая { passive: false }в качестве optionsпараметра вместо false. Однако для обратной совместимости вам нужно пройти, falseесли passiveне поддерживается поле option. См. Developer.mozilla.org/en-US/docs/Web/API/EventTarget/…
Джош Галлахер
@JoshGallagher Не могли бы вы привести рабочий пример? На iOS11 ни один из ответов не работает для меня.
Мик
«Жесткий старт» -> protectDefault работает для меня во время написания статьи на iOS 12,2
Майкл Камден,
5

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

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

Александр Качкаев
источник
5

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

window.addEventListener(
    "touchmove",
    function(event) {
        if (event.scale !== 1) {
            event.preventDefault();
        }
    },
    { passive: false }
);
Хамед
источник
Мой вариант использования - это также полностраничная 3d-сцена с пользовательскими элементами управления пинчем. Я был бы потоплен, если бы не было обходного пути для Apple, явно игнорирующей пользовательский масштаб: нет мета.
Ник Билык
1

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

  1. Слушатель onClick - это может быть простой noop.
  2. cursor: pointerНабор в CSS
mariomc
источник
как насчет защемления?
Сам Су
К сожалению, масштабирование не предусмотрено этим решением. Для этого мы использовали решение, предложенное в: stackoverflow.com/a/39594334/374196
mariomc
Не работает для меня Я использую 10.2.1 Beta 4 на iPod Touch, используя эту тестовую страницу, и дважды
robocat
1
Я имею это на промежутке в приложении реакции, и это не работает.
FMD
1

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

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

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

<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

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

lukejacksonn
источник
1

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

    // 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);
Синтаксис
источник
1

В ответ на запрос я передал свой комментарий на ответ, чтобы люди могли его проголосовать:

Это работает 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">

Стерлинг борн
источник
0

Я проверил все вышеупомянутые ответы на практике со своей страницей на 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)'
    }
});
Петр Ковальский
источник
К сожалению, это работает только тогда, когда ваша страница идеально подходит, а не когда у вас есть прокручиваемый контент
Shoe
Хм. По моему опыту, это прекрасно работает с прокручиваемым контентом (iOS 10.3).
jeff_mcmahan
0

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

document.documentElement.addEventListener('touchmove', function (event) {
    event.preventDefault();
}, false);
Диего Санта Круз Мендесу
источник
Я попробовал это, он предотвратил масштабирование, но он отключил сенсорную прокрутку окна просмотра, поэтому вы больше не можете прокручивать страницу вверх и вниз.
TGR