Как заблокировать ориентацию в портретном режиме в веб-приложении iPhone?

160

Я создаю веб-приложение для iPhone и хочу заблокировать ориентацию в портретном режиме. Это возможно? Существуют ли расширения веб-набора для этого?

Обратите внимание, что это приложение, написанное на HTML и JavaScript для Mobile Safari, это НЕ нативное приложение, написанное на Objective-C.

Kevin
источник
1
Вся причина создания веб-приложения, а не нативного, заключается в том, что оно может быть кроссплатформенным. Зачем вам создавать веб-приложение для iPhone, вы хотите написать дополнительный код для блокировки других телефонов ???
Связанный: stackoverflow.com/questions/5298467/…
xdhmoore
1
Я заинтересован в решении, которое предназначено для «маленьких экранов», а не только для вещей, которые 320px и сделаны Apple.
Шерифдерек

Ответы:

70

Вы можете указать стили CSS на основе ориентации области просмотра: нацелить браузер с помощью body [orient = "landscape"] или body [orient = "Portrait"]

http://www.evotech.net/blog/2007/07/web-development-for-the-iphone/

Тем не мение...

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

http://ask.metafilter.com/99784/How-can-I-lock-iPhone-orientation-in-Mobile-Safari

Скотт Фокс
источник
Спасибо, но я уже делаю эту часть, и я хочу, чтобы Mobile Safari не менял ориентацию, когда пользователь наклоняет телефон.
Кевин
4
Подход Apple к этому вопросу заключается в том, чтобы позволить разработчику изменять CSS в зависимости от изменения ориентации, но не полностью предотвращать переориентацию. Я нашел похожий вопрос в другом месте: ask.metafilter.com/99784/…
Скотт Фокс
2
Я видел, что на некоторых сайтах отображается только альбомное сообщение, информирующее пользователя о том, что этот сайт можно просматривать только в портретной ориентации - еще один вариант, который вы должны рассмотреть.
Джейден Лоусон
97

Это довольно хакерское решение, но это хоть что-то (?). Идея состоит в том, чтобы использовать CSS-преобразование, чтобы повернуть содержимое вашей страницы в квазипортретный режим. Вот код JavaScript (выраженный в jQuery) для начала:

$(document).ready(function () {
  function reorient(e) {
    var portrait = (window.orientation % 180 == 0);
    $("body > div").css("-webkit-transform", !portrait ? "rotate(-90deg)" : "");
  }
  window.onorientationchange = reorient;
  window.setTimeout(reorient, 0);
});

Код ожидает, что все содержимое вашей страницы будет находиться внутри элемента div внутри элемента body. В альбомном режиме он поворачивается на 90 градусов - обратно в портрет.

Оставьте читателю в качестве упражнения: div вращается вокруг своей центральной точки, поэтому его положение, вероятно, нужно будет отрегулировать, если оно не будет совершенно квадратным.

Кроме того, есть не привлекательная визуальная проблема. Когда вы меняете ориентацию, Safari вращается медленно, а затем div верхнего уровня привязывается к 90 градусам. Для еще большего удовольствия добавьте

body > div { -webkit-transition: all 1s ease-in-out; }

на ваш CSS. Когда устройство вращается, то Safari делает, а содержание вашей страницы. Начинка!

Grumdrig
источник
3
Грумдриг, ты мой герой! Это самый полезный и работающий совет, связанный с веб-приложением для iPhone, который я когда-либо видел на этом сайте. Большое спасибо!
Noober
Прежде чем я прочитал этот ответ, я собирался предложить на «принятых» комментариях ответа, что кто-то еще должен попробовать это и сказать мне, если это сработало. Я действительно рад, что кто-то уже сделал, и что это сделал!
переулок
что если div прямоугольный? по какой формуле правильно установить источник преобразования? TA
Superjos
Вы также можете управлять им с помощью опции «Поддерживаемая ориентация интерфейса» на xCode в разделе «Информация о разработке для Iphone / iPod». Работал хорошо
Родриго Диас
1
мы не можем вращать само тело напрямую? Скажем, $ ("body"). Css ("- webkit-transform",! Portrait? "Rotate (-90deg)": "");
Кришна Чайтанья
39

Этот ответ пока невозможен, но я публикую его для "будущих поколений". Надеемся, что когда-нибудь мы сможем сделать это с помощью правила CSS @viewport:

@viewport {
    orientation: portrait;
}

Вот страница «Могу ли я использовать» (по состоянию на 2019 год только IE и Edge):
https://caniuse.com/#feat=mdn-css_at-rules_viewport_orientation

Спецификация (в процессе):
https://drafts.csswg.org/css-device-adapt/#orientation-desc

MDN:
https://developer.mozilla.org/en-US/docs/Web/CSS/@viewport/orientation

Исходя из таблицы совместимости браузера MDN и следующей статьи, похоже, что есть некоторая поддержка в определенных версиях IE и Opera:
http://menacingcloud.com/?c=cssViewportOrMetaTag

Эта спецификация JS API также выглядит уместно:
https://w3c.github.io/screen-orientation/

Я предполагал, что, поскольку это было возможно с предложенным @viewportправилом, это было бы возможно путем установки orientationв настройках области просмотра в metaтеге, но я до сих пор не добился успеха в этом.

Не стесняйтесь обновлять этот ответ по мере улучшения ситуации.

xdhmoore
источник
К 10/2019 эта новая функция еще не работает. Пожалуйста, держите нас в курсе. Спасибо.
RainCast
2
В самом деле, это заняло так много времени, и мне интересно, будет ли это когда-либо Я добавил ссылку на страницу "CanIUse".
xdhmoore
Спасибо. Вы владелец этой функции? Я не совсем понимаю, как выпущена новая функция CSS. По моему мнению, css org говорит с каждым из основных владельцев браузерных продуктов и просит их поддержать его? Кто контролирует процесс? Я очень любопытная.
RainCast
Нет другого разработчика. Вы ищете W3C.
xdhmoore
19

Следующий код был использован в нашей html5 игре.

$(document).ready(function () {
     $(window)    
          .bind('orientationchange', function(){
               if (window.orientation % 180 == 0){
                   $(document.body).css("-webkit-transform-origin", "")
                       .css("-webkit-transform", "");               
               } 
               else {                   
                   if ( window.orientation > 0) { //clockwise
                     $(document.body).css("-webkit-transform-origin", "200px 190px")
                       .css("-webkit-transform",  "rotate(-90deg)");  
                   }
                   else {
                     $(document.body).css("-webkit-transform-origin", "280px 190px")
                       .css("-webkit-transform",  "rotate(90deg)"); 
                   }
               }
           })
          .trigger('orientationchange'); 
});
Андрей Шнайдер
источник
Как вы узнаете эти числа для источника трансформации?
Superjos
3
Предупреждение!!! Не все устройства сообщают об одинаковых значениях ориентации, поэтому на них нельзя положиться matthewgifford.com/blog/2011/12/22/…
Роб
6

Я придумал этот метод CSS только для поворота экрана с помощью медиа-запросов. Запросы основаны на размерах экрана, которые я нашел здесь . 480px показалось хорошим, так как ни одно / несколько устройств не имели ширину более 480px или высоту менее 480px.

@media (max-height: 480px) and (min-width: 480px) and (max-width: 600px) { 
    html{
        -webkit-transform: rotate(-90deg);
           -moz-transform: rotate(-90deg);
            -ms-transform: rotate(-90deg);
             -o-transform: rotate(-90deg);
                transform: rotate(-90deg);
        -webkit-transform-origin: left top;
           -moz-transform-origin: left top;
            -ms-transform-origin: left top;
             -o-transform-origin: left top;
                transform-origin: left top;
        width: 320px; /*this is the iPhone screen width.*/
        position: absolute;
        top: 100%;
            left: 0
    }
}
Билл
источник
+1 хорошее решение. У меня есть нижний колонтитул, положение которого зафиксировано снизу. Есть идеи, как отобразить его после поворота?
Cybrix
1
Как насчет использования (direction: landscape) в медиа-запросе вместо конкретных значений пикселей? Или необходимо определить точное значение пикселя?
Джастин Путни
Я использовал значение в пикселях, потому что вы должны установить точное значение в HTML, которое должно соответствовать высоте экрана (когда в альбомной ориентации - так ширина экрана). Таким образом, использование orientation: landscapeне будет работать так хорошо в моем примере @JustinPutney
Билл
1
От MDN: «Примечание. Это значение не соответствует фактической ориентации устройства. Открытие программной клавиатуры на большинстве устройств в портретной ориентации приведет к тому, что область просмотра станет шире, чем она будет высокой, в результате чего браузер будет использовать альбомные стили вместо портретного». "
шерифдерек
2
Ориентация @ media rules --- да. Думал, что это был путь, пока я не прочитал это: developer.mozilla.org/en-US/docs/Web/Guide/CSS/…
sheriffderek
2

Возможно, в новом будущем у него будет нестандартное решение ...

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

есть экспериментальная функциональность, которая делает это.

Но это работает только на Firefox 18+, IE11 + и Chrome 38+.

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

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

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

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

lockOrientation("landscape-primary");
Фабио Ноласко
источник
Я использую его в своем JavaScript-коде на моем WordPress-сайте как: screen.lockOrientation ("landscape"); и это не работает. Я получаю: jQuery (...). LockOrientation не является функцией. Мне нужно реализовать какой-либо плагин или фреймворк?
Алекс Станезе
1

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

Сначала определите ориентацию или переориентацию устройства и, используя 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%);
}
Реджи Пинкхем
источник
0
// CSS hack to prevent layout breaking in landscape
// e.g. screens larger than 320px  
html {
  width: 320px;
  overflow-x: hidden;
}

Это или подобное CSS-решение, по крайней мере, сохранит ваш макет, если это то, что вам нужно.

Корневое решение учитывает возможности устройства, а не пытается их ограничить. Если устройство не допускает соответствующих ограничений, тогда лучшим выбором будет простой взлом, так как дизайн по сути неполный. Чем проще, тем лучше.

dgoldston
источник
0

В кофе, если это кому-нибудь нужно.

    $(window).bind 'orientationchange', ->
        if window.orientation % 180 == 0
            $(document.body).css
                "-webkit-transform-origin" : ''
                "-webkit-transform" : ''
        else
            if window.orientation > 0
                $(document.body).css
                    "-webkit-transform-origin" : "200px 190px"
                    "-webkit-transform" : "rotate(-90deg)"
            else
                $(document.body).css
                    "-webkit-transform-origin" : "280px 190px"
                    "-webkit-transform" : "rotate(90deg)"
Филипп
источник
0

Вдохновленный ответом @ Grumdrig, а также потому, что некоторые из использованных инструкций не будут работать, я предлагаю следующий сценарий, если это потребуется кому-то еще:

    $(document).ready(function () {

      function reorient(e) {
        var orientation = window.screen.orientation.type;
        $("body > div").css("-webkit-transform", (orientation == 'landscape-primary' || orientation == 'landscape-secondary') ? "rotate(-90deg)" : "");
      }
    $(window).on("orientationchange",function(){
        reorient();
    });
      window.setTimeout(reorient, 0);
    });
Язид Эрман
источник
0

У меня похожая проблема, но для создания ландшафта ... Я считаю, что код ниже должен помочь:

//This code consider you are using the fullscreen portrait mode
function processOrientation(forceOrientation) {
  var orientation = window.orientation;
  if (forceOrientation != undefined)
    orientation = forceOrientation;
  var domElement = document.getElementById('fullscreen-element-div');
  switch(orientation) {
    case 90:
      var width = window.innerHeight;
      var height = window.innerWidth;
      domElement.style.width = "100vh";
      domElement.style.height = "100vw";
      domElement.style.transformOrigin="50% 50%";
      domElement.style.transform="translate("+(window.innerWidth/2-width/2)+"px, "+(window.innerHeight/2-height/2)+"px) rotate(-90deg)";
      break;
    case -90:
      var width = window.innerHeight;
      var height = window.innerWidth;
      domElement.style.width = "100vh";
      domElement.style.height = "100vw";
      domElement.style.transformOrigin="50% 50%";
      domElement.style.transform="translate("+(window.innerWidth/2-width/2)+"px, "+(window.innerHeight/2-height/2)+"px) rotate(90deg)";
      break;
    default:
      domElement.style.width = "100vw";
      domElement.style.height = "100vh";
      domElement.style.transformOrigin="";
      domElement.style.transform="";
      break;
  }
}
window.addEventListener('orientationchange', processOrientation);
processOrientation();
<html>
<head></head>
<body style="margin:0;padding:0;overflow: hidden;">
  <div id="fullscreen-element-div" style="background-color:#00ff00;width:100vw;height:100vh;margin:0;padding:0"> Test
  <br>
  <input type="button" value="force 90" onclick="processOrientation(90);" /><br>
  <input type="button" value="force -90" onclick="processOrientation(-90);" /><br>
  <input type="button" value="back to normal" onclick="processOrientation();" />
  </div>
</body>
</html>

ARibeiro
источник
-3

Нажмите здесь для учебного и рабочего примера с моего сайта.

Вам больше не нужно использовать хаки только для того, чтобы посмотреть jQuery Mobile Screen Orientation, и вы больше не должны использовать PhoneGap, если вы на самом деле не используете PhoneGap.

Чтобы сделать эту работу в 2015 году нам нужно:

  • Cordova (лучше любая версия выше 4.0)
  • PhoneGap (вы даже можете использовать PhoneGap, плагины совместимы)

И один из этих плагинов в зависимости от вашей версии Cordova:

  • net.yoik.cordova.plugins.screenorientation (Cordova <4)

плагин Cordova добавить нет.yoik.cordova.plugins.screenorientation

  • Cordova плагин добавить Cordova-плагин-экран-ориентация (Cordova> = 4)

Cordova плагин добавить Cordova-плагин-экран-ориентация

А для блокировки ориентации экрана просто используйте эту функцию:

screen.lockOrientation('landscape');

Чтобы разблокировать это:

screen.unlockOrientation();

Возможные ориентации:

  • Portrait-primary Ориентация в основном режиме портрета.

  • портрет-вторичный Ориентация в режиме вторичного портрета.

  • альбомная ориентация Ориентация в основном ландшафтном режиме.

  • ландшафт-вторичный Ориентация в режиме вторичного ландшафта.

  • Книжная ориентация - портретно-первичная или портретно-вторичная (сенсор).

  • альбомная ориентация - ландшафтно-первичная или ландшафтно-вторичная (датчик).

Gajotres
источник