Предотвратить изменение ориентации в iOS Safari

Можно ли избежать перехода в альбомную ориентацию в Safari для iOS при повороте устройства?

В iOS Safari есть событие "orentationchange", я попытался перехватить его и отключить поведение по умолчанию, например:

<html>
<head>
<script type="text/javascript">
function changeOrientation(event) {
    alert("Rotate");
    event.preventDefault();
}
</script>
</head>
<body onorientationchange="changeOrientation(event);">
PAGE CONTENT
</body>
</html>

но при тестировании страницы на моем iPhone, когда я поворачиваю устройство, отображается предупреждение, но вид переключается в альбомную ориентацию. Кажется, что event.preventDefault() не останавливает вращение.

Есть ли способ заблокировать это поведение?

10 ответов

Решение

В Mobile Safari нет способа навязать определенную ориентацию; он всегда будет автоматически поворачиваться, когда пользователь поворачивает свое устройство.

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

Джонатан Снук обходит эту проблему. На своих слайдах он показывает, как (вроде) заблокировать портрет (см. Слайды 54 и 55).

Код JS из этих слайдов:

window.addEventListener('orientationchange', function () {
    if (window.orientation == -90) {
        document.getElementById('orient').className = 'orientright';
    }
    if (window.orientation == 90) {
        document.getElementById('orient').className = 'orientleft';
    }
    if (window.orientation == 0) {
        document.getElementById('orient').className = '';
    }
}, true);

и CSS:

.orientleft #shell {
    -webkit-transform: rotate(-90deg);
    -webkit-transform-origin:160px 160px;
}

.orientright #shell {
    -webkit-transform: rotate(90deg);
    -webkit-transform-origin:230px 230px;
} 

Я пытался заставить это работать для пейзажа на iPhone, но это никогда не выглядело на 100% правильным. Однако я подошел ближе к следующему коду jQueryian. Это будет в рамках функции onready. Также обратите внимание: это было в контексте "сохранено на домашний экран", и я думаю, что это изменило положение источника преобразования.

$(window).bind('orientationchange', function(e, onready){
   if(onready){
       $(document.body).addClass('portrait-onready');
   }
   if (Math.abs(window.orientation) != 90){
       $(document.body).addClass('portrait');
   } 
   else {
       $(document.body).removeClass('portrait').removeClass('portrait-onready');
   }
});
$(window).trigger('orientationchange', true); // fire the orientation change event at the start, to make sure 

И CSS:

.portrait {
    -webkit-transform: rotate(90deg);
    -webkit-transform-origin: 200px 190px;
}
.portrait-onready {
    -webkit-transform: rotate(90deg);
    -webkit-transform-origin: 165px 150px;
}

Надеюсь, что это поможет кому-то приблизиться к желаемому результату...

Хотя вы не можете предотвратить вступление в силу изменения ориентации, вы не можете эмулировать изменения, как указано в других ответах.

Сначала определите ориентацию устройства или переориентацию и, используя JavaScript, добавьте имя класса в элемент обертывания (в этом примере я использую тег body).

function deviceOrientation() {
  var body = document.body;
  switch(window.orientation) {
    case 90:
      body.classList = '';
      body.classList.add('rotation90');
      break;
    case -90:
      body.classList = '';
      body.classList.add('rotation-90');
      break;
    default:
      body.classList = '';
      body.classList.add('portrait');
      break;
  }
}
window.addEventListener('orientationchange', deviceOrientation);
deviceOrientation();

Затем, если устройство имеет альбомную ориентацию, используйте CSS, чтобы установить ширину тела для высоты области просмотра и высоту тела для ширины области просмотра. И давайте установим источник преобразования, пока мы на нем.

@media screen and (orientation: landscape) {
  body {
    width: 100vh;
    height: 100vw;
    transform-origin: 0 0;
  }
}

Теперь переориентируйте элемент body и сдвиньте (переведите) его в нужное положение.

body.rotation-90 {
  transform: rotate(90deg) translateY(-100%);
}
body.rotation90 {
  transform: rotate(-90deg) translateX(-100%);
}

Была предложена спецификация для реализации этой функциональности.

Также смотрите эту ошибку Chromium для получения дополнительной информации (пока неясно, будет ли она реализована в WebKit или Chromium).

Может быть, в новом будущем...

По состоянию на май 2015 года

есть экспериментальная функциональность, которая делает это. Но это работает только на Firefox 18+, IE11+ и Chrome 38+.

Тем не менее, он не работает на Opera или Safari.

https://developer.mozilla.org/en-US/docs/Web/API/Screen/lockOrientation

Вот текущий код для совместимых браузеров:

var lockOrientation = screen.lockOrientation || screen.mozLockOrientation || screen.msLockOrientation;

lockOrientation("landscape-primary");

Следующее решение, похоже, работает на iPhone4, 5, 6 и 6+ с июня 2016 года.

<script>
  /**
   * we are locking mobile devices orientation to portrait mode only
   */
  var devWidth, devHeight;
  window.addEventListener('load', function() {
    devWidth  = screen.width;
    devHeight = screen.height;
  });
  window.addEventListener('orientationchange', function () {
    if (devWidth < 768 && (window.orientation === 90 || window.orientation == -90)) {
      document.body.style.width = devWidth + 'px';
      document.body.style.height = devHeight + 'px';
      document.body.style.transform = 'rotate(90deg)';
      document.body.style.transformOrigin = ''+(devHeight/2)+'px '+(devHeight/2)+'px';
    } else {
      document.body.removeAttribute('style');
    }
  }, true);
</script>

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

Еще не проверял это на iPhone, но вы можете попробовать

      screen.orientation.lock('portrait');
screen.orientation.unlock();

Дополнительная информация на MDN

Я тестирую этот способ работы для меня:

@media (orientation: portrait) {
  body {
    transform: rotate(-90deg);
  }
}

Если это возможно (что я не верю, что это так), то я настоятельно рекомендую против этого. Пользователи ненавидят, когда их заставляют просматривать страницы определенным образом. Что если они используют свой iphone в док-станции и не могут вынести его в ландшафтном режиме, не отсоединив его, или что, если они предпочитают альбомную версию клавиатуры, потому что клавиши больше?

Если ваш дизайн требует определенной ориентации, вы можете пересмотреть свой дизайн.

Другие вопросы по тегам