Jak zablokować orientację w trybie pionowym w aplikacji internetowej na telefon iPhone?

160

Tworzę aplikację internetową na iPhone'a i chcę zablokować orientację w trybie pionowym. czy to możliwe? Czy są jakieś rozszerzenia zestawu internetowego, które to umożliwiają?

Należy pamiętać, że jest to aplikacja napisana w HTML i JavaScript dla Mobile Safari, NIE jest to natywna aplikacja napisana w Objective-C.

Kevin
źródło
1
Cały powód tworzenia aplikacji internetowej, a nie aplikacji natywnej, jest taki, że może być ona wieloplatformowa. Dlaczego miałbyś tworzyć aplikację internetową na iPhone'a, czy szukasz dodatkowego kodu, aby zablokować inne telefony?
1
Interesuje mnie rozwiązanie przeznaczone do „małych ekranów”, a nie tylko do rzeczy 320px wykonanych przez Apple.
szeryfderek

Odpowiedzi:

70

Możesz określić style CSS na podstawie orientacji widoku: kieruj na przeglądarkę treścią [orient = "pozioma"] lub treścią [orient = "portret"]

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

Jednak...

Podejście Apple do tego problemu polega na umożliwieniu programistom zmiany CSS na podstawie zmiany orientacji, ale bez całkowitego zapobiegania ponownej orientacji. Znalazłem podobne pytanie gdzie indziej:

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

Scott Fox
źródło
Dzięki, ale już robię tę część, naprawdę chcę, aby Mobile Safari nie przełączała na mnie orientacji, gdy użytkownik przechyla telefon.
Kevin,
4
Podejście firmy Apple do tego problemu polega na umożliwieniu programistom zmiany CSS na podstawie zmiany orientacji, ale nie w celu całkowitego zapobieżenia ponownej orientacji. Znalazłem podobne pytanie gdzie indziej: ask.metafilter.com/99784/…
Scott Fox
2
Widziałem, że niektóre witryny wyświetlają komunikat tylko w orientacji poziomej, instruujący użytkownika, że ​​tę witrynę można oglądać tylko w orientacji pionowej - to kolejna opcja do rozważenia.
Jayden Lawson,
97

To dość hakerskie rozwiązanie, ale przynajmniej coś (?). Chodzi o to, aby użyć transformacji CSS, aby obrócić zawartość strony do trybu quasi-portretu. Oto kod JavaScript (wyrażony w jQuery) na początek:

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

Kod oczekuje, że cała zawartość Twojej strony będzie znajdować się w elemencie div bezpośrednio w elemencie body. Obraca ten obszar o 90 stopni w trybie poziomym - z powrotem do portretu.

Pozostawione jako ćwiczenie dla czytelnika: element div obraca się wokół swojego punktu środkowego, więc jego położenie prawdopodobnie będzie wymagało dostosowania, chyba że jest idealnie kwadratowe.

Jest też nieatrakcyjny problem wizualny. Gdy zmienisz orientację, Safari obraca się powoli, a następnie element div najwyższego poziomu przyciąga do 90 stopni inaczej. Aby uzyskać jeszcze więcej zabawy, dodaj

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

do twojego CSS. Gdy urządzenie się obraca, to robi to Safari, a potem zawartość Twojej strony. Niesamowite!

Grumdrig
źródło
3
Grumdrig, jesteś moim bohaterem! To najbardziej przydatna i działająca wskazówka dotycząca aplikacji internetowej na iPhone'a, jaką kiedykolwiek widziałem na tej stronie. Wielkie dzięki!
listopada
Zanim przeczytałem tę odpowiedź, miałem zamiar zasugerować w komentarzach „zaakceptowanej” odpowiedzi, że ktoś INNY powinien spróbować tego i powiedzieć, czy zadziałało. Bardzo się cieszę, że ktoś już to zrobił i że tak się stało!
Lane
co jeśli element DIV jest prostokątny? jaka jest formuła, aby poprawnie ustawić początek transformacji? TA
superjos
Możesz także sterować tym za pomocą opcji „Obsługiwana orientacja interfejsu” w xCode, w informacjach o rozwoju Iphone / iPod. Pracował dobrze
Rodrigo Dias
1
czy nie możemy bezpośrednio obrócić samego ciała? Powiedz, $ ("body"). Css ("- webkit-transform",! Portrait? "Rotate (-90deg)": "");
Krsna Caitanya,
39

Ta odpowiedź nie jest jeszcze możliwa, ale zamieszczam ją dla „przyszłych pokoleń”. Mamy nadzieję, że pewnego dnia będziemy mogli to zrobić za pomocą reguły CSS @viewport:

@viewport {
    orientation: portrait;
}

Oto strona „Can I Use” (od 2019 r. Tylko IE i Edge):
https://caniuse.com/#feat=mdn-css_at-rules_viewport_orientation

Specyfikacja (w trakcie):
https://drafts.csswg.org/css-device-adapt/#orientation-desc

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

Na podstawie tabeli zgodności przeglądarek MDN i następującego artykułu wygląda na to, że niektóre wersje przeglądarek IE i Opera są obsługiwane:
http://menacingcloud.com/?c=cssViewportOrMetaTag

Ta specyfikacja JS API również wygląda na trafną:
https://w3c.github.io/screen-orientation/

Założyłem, że skoro jest to możliwe przy proponowanej @viewportregule, to będzie możliwe poprzez ustawienieorientation w ustawieniach rzutni w metatagu, ale jak dotąd nie udało mi się to.

W miarę poprawy sytuacji możesz zaktualizować tę odpowiedź.

xdhmoore
źródło
Do 10/2019 ta nowa funkcja jeszcze nie działa. Proszę informuj nas na bieżąco. dzięki.
RainCast
2
Rzeczywiście, trwało to tak długo, że zastanawiam się, czy kiedykolwiek tak będzie. Dodałem link do strony „CanIUse”.
xdhmoore
Dziękuję Ci. czy jesteś właścicielem tej funkcji? Nie bardzo rozumiem, jak jest udostępniana nowa funkcja CSS. Domyślam się, że organizacja css rozmawia z każdym z głównych właścicieli produktów przeglądarkowych i prosi ich o wsparcie? Kto kontroluje proces? Jestem bardzo ciekawa.
RainCast
Nie tylko kolejny programista. Szukasz W3C.
xdhmoore
19

Poniższy kod został użyty w naszej grze 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
źródło
jak obliczyć te liczby dla początku transformacji?
superjos
3
Ostrzeżenie!!! Nie wszystkie urządzenia podają te same wartości orientacyjne, więc nie można na nich polegać na matthewgifford.com/blog/2011/12/22/…
Rob
6

Wymyśliłem tę jedyną w CSS metodę obracania ekranu za pomocą zapytań o media. Zapytania są oparte na rozmiarach ekranu, które znalazłem tutaj . 480px wydawało się dobre, ponieważ żadne / kilka urządzeń nie miało więcej niż 480 pikseli szerokości lub mniej niż 480 pikseli wysokości.

@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
    }
}
Rachunek
źródło
+1 ładne rozwiązanie. Mam stopkę, która jest ustalona na dole. Masz pomysł, jak to wyświetlić po obróceniu?
Cybrix
1
Co powiesz na użycie (orientacja: pozioma) w zapytaniu o media zamiast określonych wartości pikseli? A może trzeba zdefiniować dokładną wartość piksela?
Justin Putney
Użyłem wartości piksela, ponieważ musisz ustawić dokładną wartość w html, która musi odpowiadać wysokości ekranu (w orientacji poziomej - czyli szerokość ekranu). Więc używanie orientation: landscapenie działałoby tak dobrze w moim przykładzie @JustinPutney
Bill
1
Z MDN: „Uwaga: ta wartość nie odpowiada rzeczywistej orientacji urządzenia. Otwarcie klawiatury programowej na większości urządzeń w orientacji pionowej spowoduje, że okno robocze będzie szersze niż wysokie, przez co przeglądarka będzie używać stylów poziomych zamiast pionowych. "
szeryfderek
2
Orientacja @ zasady mediów --- tak. Myślałem, że to najlepszy sposób, dopóki nie przeczytałem tego: developer.mozilla.org/en-US/docs/Web/Guide/CSS/ ...
sheriffderek
2

Może w nowej przyszłości będzie miało nieszablonowe rozwiązanie ...

Od maja 2015 r.

istnieje eksperymentalna funkcjonalność, która to robi.

Ale działa tylko w przeglądarkach Firefox 18+, IE11 + i Chrome 38+.

Jednak nie działa jeszcze w Operze ani Safari.

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

Oto aktualny kod kompatybilnych przeglądarek:

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

lockOrientation("landscape-primary");
Fabio Nolasco
źródło
Używam go w moim kodzie javascript w mojej witrynie wordpress jako: screen.lockOrientation ("krajobraz"); i to nie działa. Otrzymuję: jQuery (...). LockOrientation nie jest funkcją. Czy muszę zaimplementować jakąkolwiek wtyczkę lub framework?
Alex Stanese
1

Chociaż nie możesz zapobiec zmianie orientacji, nie możesz naśladować żadnej zmiany, jak podano w innych odpowiedziach.

Najpierw wykryj orientację lub zmianę orientacji urządzenia i za pomocą JavaScript dodaj nazwę klasy do elementu opakowującego (w tym przykładzie używam tagu 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();

Następnie, jeśli urządzenie jest w orientacji poziomej, użyj CSS, aby ustawić szerokość ciała na wysokość rzutni, a wysokość ciała na szerokość widoku. Ustawmy początek transformacji, skoro już przy tym jesteśmy.

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

Teraz zmień orientację elementu ciała i przesuń (przetłumacz) na miejsce.

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

To lub podobne rozwiązanie CSS przynajmniej zachowa twój układ, jeśli tego szukasz.

Rozwiązanie roota uwzględnia możliwości urządzenia, a nie próbuje je ograniczać. Jeśli urządzenie nie pozwala na odpowiednie ograniczenie, najlepszym rozwiązaniem jest prosty hack, ponieważ projekt jest zasadniczo niekompletny. Im prostsze, tym lepsze.

dgoldston
źródło
0

W kawie, jeśli ktoś tego potrzebuje.

    $(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
źródło
0

Zainspirowany odpowiedzią @ Grumdriga i ponieważ niektóre z użytych instrukcji nie zadziałały, sugeruję następujący skrypt, jeśli ktoś tego potrzebuje:

    $(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
źródło
0

Mam podobny problem, ale żeby zrobić krajobraz ... Uważam, że poniższy kod powinien załatwić sprawę:

//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
źródło
-3

Kliknij tutaj, aby zobaczyć samouczek i działający przykład z mojej strony internetowej.

Nie musisz już używać hacków tylko po to, by sprawdzić orientację ekranu jQuery Mobile ani nie powinieneś już używać PhoneGap, chyba że faktycznie używasz PhoneGap.

Aby to zadziałało w 2015 roku potrzebujemy:

  • Cordova (każda wersja, chociaż wszystko powyżej 4.0 jest lepsze)
  • PhoneGap (możesz nawet używać PhoneGap, wtyczki są kompatybilne)

I jedna z tych wtyczek w zależności od wersji Cordova:

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

wtyczka cordova dodaje net.yoik.cordova.plugins.screenorientation

  • wtyczka cordova dodaje orientację ekranu cordova-plugin (Cordova> = 4)

wtyczka cordova dodaje orientację ekranu cordova-plugin

Aby zablokować orientację ekranu, użyj tej funkcji:

screen.lockOrientation('landscape');

Do odblokowania tego:

screen.unlockOrientation();

Możliwe orientacje:

  • portrait-primary Orientacja jest w głównym trybie portretowym.

  • portret-drugorzędna Orientacja jest w drugorzędnym trybie portretu.

  • landscape-primary Orientacja jest w podstawowym trybie poziomym.

  • landscape-secondary Orientacja jest w drugorzędnym trybie poziomym.

  • portret Orientacja to podstawowa orientacja pionowa lub drugorzędna (czujnik).

  • pozioma Orientacja jest albo pozioma-pierwotna lub pozioma-drugorzędna (czujnik).

Gajotres
źródło