Como bloqueio a orientação para o modo retrato em um aplicativo da Web para iPhone?

160

Estou criando um aplicativo da Web para iPhone e quero bloquear a orientação no modo retrato. Isso é possível? Existem extensões de kit da web para fazer isso?

Observe que este é um aplicativo escrito em HTML e JavaScript para o Mobile Safari, NÃO é um aplicativo nativo escrito em Objective-C.

Kevin
fonte
1
Todo o motivo da criação de um aplicativo Web e não de um aplicativo nativo é que ele pode ser multiplataforma. Por que você criaria um aplicativo Web específico para iPhone? Você está escrevendo código extra para bloquear outros telefones ???
1
Estou interessado em uma solução que é para "telas pequenas" e não apenas para itens com 320px e fabricados pela apple.
precisa

Respostas:

70

Você pode especificar estilos CSS com base na orientação da janela de visualização: segmente o navegador com body [orient = "landscape"] ou body [orient = "portrait"]

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

Contudo...

A abordagem da Apple para esse problema é permitir que o desenvolvedor altere o CSS com base na alteração da orientação, mas não impedir a reorientação completamente. Encontrei uma pergunta semelhante em outro lugar:

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

Scott Fox
fonte
Obrigado, mas já estou fazendo essa parte. O que realmente quero é impedir que o Mobile Safari não mude de orientação quando o usuário inclina o telefone.
Kevin
4
A abordagem da Apple para esse problema para permitir que o desenvolvedor altere o CSS com base na mudança de orientação, mas não para impedir a reorientação completamente. Eu encontrei uma pergunta semelhante em outro lugar: ask.metafilter.com/99784/...
Scott Fox
2
Vi alguns sites mostrarem uma mensagem apenas em paisagem instruindo o usuário que este site só pode ser exibido na orientação retrato - apenas uma outra opção para você considerar.
Jayden Lawson
97

Esta é uma solução bastante hacky, mas é pelo menos alguma coisa (?). A idéia é usar uma transformação CSS para girar o conteúdo da sua página para o modo quase retrato. Aqui está o código JavaScript (expresso em jQuery) para você começar:

$(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);
});

O código espera que todo o conteúdo da sua página fique dentro de uma div, dentro do elemento body. Ele gira essa div 90 graus no modo paisagem - de volta ao retrato.

Deixado como um exercício para o leitor: o div gira em torno de seu ponto central; portanto, sua posição provavelmente precisará ser ajustada, a menos que esteja perfeitamente quadrado.

Além disso, há um problema visual desagradável. Quando você altera a orientação, o Safari gira lentamente, e a div de nível superior se ajusta a 90 graus diferentes. Para ainda mais diversão, adicione

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

para o seu CSS. Quando o dispositivo gira, o Safari gira e o conteúdo da sua página. Sedutor!

Grumdrig
fonte
3
Grumdrig, você é meu herói! Esta é a dica mais útil e funcional sobre aplicativos para iPhone para iPhone que eu já vi neste site. Muito obrigado!
noober
Antes de ler esta resposta, eu estava prestes a sugerir nos comentários de resposta "aceitos" que alguém ELSE deveria tentar isso e me dizer se funcionou. Estou realmente feliz que alguém já fez, e que fez!
Lane
e se a div for retangular? qual é a fórmula para definir corretamente a origem da transformação? TA
superjos 20/12/12
Você também pode controlá-lo com a opção "Orientação da interface suportada" no xCode, em Informações de desenvolvimento do Iphone / iPod. Funcionou bem
Rodrigo Dias
1
não podemos girar o próprio corpo diretamente? Digamos, $ ("body"). Css ("- webkit-transform",! Portrait? "Rotate (-90deg)": "");
Krsna Chaitanya
39

Essa resposta ainda não é possível, mas estou publicando-a para "gerações futuras". Felizmente, um dia seremos capazes de fazer isso através da regra CSS @viewport:

@viewport {
    orientation: portrait;
}

Aqui está a página "Posso usar" (somente em 2019, IE e Edge):
https://caniuse.com/#feat=mdn-css_at-rules_viewport_orientation

Especificação (em processo):
https://drafts.csswg.org/css-device-adapt/#orientation-desc

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

Com base na tabela de compatibilidade do navegador MDN e no artigo a seguir, parece haver algum suporte em determinadas versões do IE e Opera:
http://menacingcloud.com/?c=cssViewportOrMetaTag

Essa especificação da API JS também parece relevante:
https://w3c.github.io/screen-orientation/

Eu assumi que, como era possível com a @viewportregra proposta , isso seria possível definindo orientationas configurações da janela de exibição em uma metatag, mas não tive sucesso com isso até agora.

Sinta-se à vontade para atualizar esta resposta à medida que as coisas melhorarem.

xdhmoore
fonte
Até 10/2019, este novo recurso ainda não está funcionando. Por favor, mantenha-nos informados. obrigado.
RainCast 24/10/19
2
De fato, demorou tanto tempo que me pergunto se algum dia será. Adicionei um link para a página "CanIUse".
Xdhmoore 25/10/19
obrigado. você é o proprietário desse recurso? Não entendo bem como um novo recurso css é lançado. No meu palpite, a organização css conversa com cada um dos principais proprietários de produtos de navegadores e pede que eles o apoiem? Quem controla o processo? Estou muito curioso.
RainCast 26/10/19
Ha não apenas mais um desenvolvedor. Você está procurando o W3C.
Xdhmoore 26/10/19
19

O código a seguir foi usado em nosso jogo 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'); 
});
Andrei Schneider
fonte
como você descobre esses números para a origem da transformação?
superjos
3
Aviso!!! Nem todos os dispositivos informar os mesmos valores para orientação por isso não pode ser invocado matthewgifford.com/blog/2011/12/22/...
Rob
6

Eu vim com esse único método CSS de girar a tela usando consultas de mídia. As consultas são baseadas nos tamanhos de tela que encontrei aqui . 480px parecia ser bom, já que poucos dispositivos tinham mais de 480px de largura ou menos de 480px de altura.

@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
    }
}
Conta
fonte
Uma boa solução. Eu tenho um rodapé que é posição fixa na parte inferior. Alguma idéia de como exibi-lo após a rotação?
precisa
1
Que tal usar (orientação: paisagem) na consulta de mídia em vez de valores específicos de pixel? Ou é necessário definir um valor exato de pixel?
Justin Putney
Eu usei um valor de pixel porque você deve definir um valor exato no html, que deve corresponder à altura da tela (quando estiver na paisagem - portanto, na largura da tela). Então, usando orientation: landscapenão iria funcionar tão bem no meu exemplo @JustinPutney
Bill
1
Do MDN: "Nota: esse valor não corresponde à orientação real do dispositivo. Abrir o teclado virtual na maioria dos dispositivos na orientação retrato fará com que a janela de visualização fique mais larga do que alta, fazendo com que o navegador use estilos de paisagem em vez de retrato. "
precisa
2
Orientação @ regras da mídia --- sim. Pensei que eles eram o caminho a percorrer até que eu leia isto: developer.mozilla.org/en-US/docs/Web/Guide/CSS/...
sheriffderek
2

Talvez em um novo futuro ele tenha uma solução pronta para uso imediato ...

Em maio de 2015,

existe uma funcionalidade experimental que faz isso.

Mas ele funciona apenas no Firefox 18+, IE11 + e Chrome 38+.

No entanto, ainda não funciona no Opera ou no Safari.

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

Aqui está o código atual para os navegadores compatíveis:

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

lockOrientation("landscape-primary");
Fabio Nolasco
fonte
Estou usando-o no meu código javascript no meu site wordpress como: screen.lockOrientation ("landscape"); e isso não funciona. Eu recebo: jQuery (...). LockOrientation não é uma função. Preciso implementar algum plugin ou estrutura?
Alex Stanese
1

Embora você não possa impedir que a mudança de orientação seja efetivada, você não pode emular nenhuma alteração, conforme indicado em outras respostas.

Primeiro, detecte a orientação ou reorientação do dispositivo e, usando JavaScript, adicione um nome de classe ao seu elemento de quebra automática (neste exemplo, eu uso a tag 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();

Então, se o dispositivo estiver em paisagem, use CSS para definir a largura do corpo para a altura da viewport e a altura do corpo para a largura da viewport. E vamos definir a origem da transformação enquanto estamos nisso.

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

Agora, reoriente o elemento do corpo e deslize (traduza) para a posição.

body.rotation-90 {
  transform: rotate(90deg) translateY(-100%);
}
body.rotation90 {
  transform: rotate(-90deg) translateX(-100%);
}
Reggie Pinkham
fonte
0
// CSS hack to prevent layout breaking in landscape
// e.g. screens larger than 320px  
html {
  width: 320px;
  overflow-x: hidden;
}

Esta, ou uma solução CSS semelhante, preservará pelo menos seu layout, se é isso que você procura.

A solução raiz é responsável pelos recursos do dispositivo, em vez de tentar limitá-los. Se o dispositivo não permitir a limitação apropriada, um simples hack é a melhor opção, pois o design é essencialmente incompleto. Quanto mais simples, melhor.

Dgoldston
fonte
0

No café, se alguém precisar.

    $(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)"
Philip
fonte
0

Inspirado na resposta de @ Grumdrig, e como algumas das instruções usadas não funcionariam, sugiro o seguinte script, se necessário por outra pessoa:

    $(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);
    });
Yazid Erman
fonte
0

Eu tenho um problema semelhante, mas para fazer paisagem ... acredito que o código abaixo deve fazer o truque:

//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
fonte
-3

Clique aqui para obter um tutorial e um exemplo de trabalho no meu site.

Você não precisa mais usar hacks apenas para procurar a orientação da tela do jQuery Mobile, nem usar o PhoneGap, a menos que esteja usando o PhoneGap.

Para fazer isso funcionar no ano de 2015, precisamos:

  • Cordova (qualquer versão acima de 4.0 é melhor)
  • PhoneGap (você pode até usar o PhoneGap, plugins são compatíveis)

E um desses plugins, dependendo da sua versão do Cordova:

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

plug-in cordova add net.yoik.cordova.plugins.screenorientation

  • plug-in cordova add cordova-plugin-screen-orientation (Cordova> = 4)

plug-in cordova adicionar orientação-plug-in-tela-cordova

E para bloquear a orientação da tela, use esta função:

screen.lockOrientation('landscape');

Para desbloqueá-lo:

screen.unlockOrientation();

Orientações possíveis:

  • retrato-primário A orientação está no modo retrato primário.

  • retrato-secundário A orientação está no modo retrato secundário.

  • paisagem primária A orientação está no modo paisagem primária.

  • paisagem secundária A orientação está no modo paisagem secundária.

  • retrato A orientação é retrato primário ou retrato secundário (sensor).

  • paisagem A orientação é paisagem primária ou paisagem secundária (sensor).

Gajotres
fonte