İOS'ta Phonegap kullanarak yön değişikliğini nasıl doğru bir şekilde tespit edebilirim?


178

Bu yönlendirme test kodunu aşağıda JQTouch referans malzemesi ararken buldum. Bu, mobil Safari'deki iOS simülatöründe doğru çalışır, ancak Phonegap'ta doğru şekilde ele alınmaz. Projem, bu test sayfasını öldüren aynı sorunla karşılaşıyor. Phonegap'ta JavaScript kullanarak yön değişikliğini algılamanın bir yolu var mı?

window.onorientationchange = function() {
  /*window.orientation returns a value that indicates whether iPhone is in portrait mode, landscape mode with the screen turned to the
    left, or landscape mode with the screen turned to the right. */
  var orientation = window.orientation;
  switch (orientation) {
    case 0:
      /* If in portrait mode, sets the body's class attribute to portrait. Consequently, all style definitions matching the body[class="portrait"] declaration
         in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "portrait");

      /* Add a descriptive message on "Handling iPhone or iPod touch Orientation Events"  */
      document.getElementById("currentOrientation").innerHTML = "Now in portrait orientation (Home button on the bottom).";
      break;

    case 90:
      /* If in landscape mode with the screen turned to the left, sets the body's class attribute to landscapeLeft. In this case, all style definitions matching the
         body[class="landscapeLeft"] declaration in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "landscape");

      document.getElementById("currentOrientation").innerHTML = "Now in landscape orientation and turned to the left (Home button to the right).";
      break;

    case -90:
      /* If in landscape mode with the screen turned to the right, sets the body's class attribute to landscapeRight. Here, all style definitions matching the
         body[class="landscapeRight"] declaration in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "landscape");

      document.getElementById("currentOrientation").innerHTML = "Now in landscape orientation and turned to the right (Home button to the left).";
      break;
  }
}

Yanıtlar:


297

Bu benim işim:

function doOnOrientationChange() {
    switch(window.orientation) {  
      case -90: case 90:
        alert('landscape');
        break; 
      default:
        alert('portrait');
        break; 
    }
}
  
window.addEventListener('orientationchange', doOnOrientationChange);
  
// Initial execution if needed
doOnOrientationChange();


Mayıs 2019 Güncellemesi: window.orientation kullanımdan kaldırılmış bir özelliktir ve MDN'ye göre çoğu tarayıcı tarafından desteklenmemektedir . orientationchangeOlay olduğunu window.orientation ile ilişkili ve bu nedenle muhtemelen kullanılmamalıdır.


3
Bu tartışmadan benim için çalışan tek çözüm :) +1
Atadj

9
Yaptığımwindow.onorientationchange = function() { setTimeout(functionName, 0); };
Kirk Ströbeck

11
İlgilenmiyorum, neden setTimeout Kirk'ü kullandınız?
backdesk

10
Dikkatli ol! Bu cihaza özeldir - dereceler, cihazların standart oryantasyonundan farkı ifade eder. Başka bir deyişle, tablet manzarada kullanılmak üzere tasarlanmışsa, 90 dikey modda olduğu anlamına gelir. Bunun etrafında bir çalışma olarak, başlangıçta yönlendirmeyi saklamak için pencerenin yüksekliğine karşı genişliğini kontrol ediyorum ve bir değişiklik varsa bunu güncellemek için orientationchange'i kullanıyorum.
benallansmith

15
Buna ek olarak, genişlik ve yükseklik değiştirilmeden önce yön değiştirme değiştiğini fark ettim, bu nedenle genişlik ve yüksekliği kullanarak yönlendirmeyi doğru bir şekilde algılamak için biraz gecikme gerekiyor. Bunun için, geçerli yönlendirmeyi depolarım ve bir değişiklik algılandığında, 250ms'ye kadar 50ms'lik artışlarla yönelimdeki değişikliği kontrol ederim. Bir fark bulunduğunda, sayfayı buna göre güncelledim. Nexus 5'imde, genellikle 150ms'den sonra genişlik ve yükseklik farkını algılar.
benallansmith

24

Ben kullanıyorum window.onresize = function(){ checkOrientation(); } ve checkOrientation'ta window.orientation veya gövde genişliği kontrolünü kullanabilirsiniz, ancak fikir "window.onresize" en azından tarayıcı ve mobil tarayıcıların çoğunda sahip olduğum en çapraz tarayıcı yöntemidir. test etme fırsatı.


1
Bu harika bir nokta. Web'e dönük bir teknoloji kullanarak geliştiriyorsanız, bu yöntem her seferinde dağıtmak / simüle etmek yerine bir tarayıcıda daha kolay hata ayıklamanıza ve test etmenize olanak tanır.
Matt Ray

2
Bu hiç iyi değil ... çünkü klavye göründüğünde yeniden boyutlandırılacak (ve bu tek durum değil). Bunun için büyük bir hayır!
HellBaby

2
@HellBaby Klavye göründüğünde işlev çağrılır, ancak yön algılaması için hangi yöntemi kullandığınıza bağlı olarak, pencerede olduğu gibi yönlendirmenin DEĞİŞTİRİLMEDİĞİNİ algılar. Oryantasyon. Bu yüzden hala cevabımın yanındayım.
hndcrftd

1
@Raine Bu yöntemi bir Ipad 4'te kullandım ve bu sorunun nedeni olarak değiştirmek zorunda kaldım. Belki de bazı cihazlar için çalışıyor ama herkes için değil ..
HellBaby

1
@MattRay Bu tür aygıt davranışlarını taklit edebilen en yeni geliştirici araç kitleriyle yön değişikliklerini kolayca test edebilirsiniz.
kontur

14
if (window.matchMedia("(orientation: portrait)").matches) {
   // you're in PORTRAIT mode
}

if (window.matchMedia("(orientation: landscape)").matches) {
  // you're in LANDSCAPE mode
}

1
Bir resizeetkinliğe ekleyebilirsiniz . Ancak IIRC, bu sorgular klavye yukarıdayken düzgün çalışmaz.
adi518

12

İOS ve Phonegap için de oldukça yeniyim, ancak bunu bir eventListener ekleyerek yapabildim. Aynı şeyi yaptım (referans verdiğiniz örneği kullanarak) ve işe yaramadım. Ama bu hile gibi görünüyordu:

// Event listener to determine change (horizontal/portrait)
window.addEventListener("orientationchange", updateOrientation); 

function updateOrientation(e) {
switch (e.orientation)
{   
    case 0:
        // Do your thing
        break;

    case -90:
        // Do your thing
        break;

    case 90:
        // Do your thing
        break;

    default:
        break;
    }
}

PhoneGap Google Grubunda "yönlendirme" terimini aramakta biraz şansınız olabilir .

Oryantasyonun nasıl tespit edileceğine dair bir örnek olarak okuduğum bir örnek Pie Guy: ( game , js file ) idi. Gönderdiğiniz koda benzer, ama sizin gibi ... Çalışamadım.

Bir uyarı: eventListener benim için çalıştı, ama bunun aşırı yoğun bir yaklaşım olup olmadığından emin değilim. Şimdiye kadar benim için çalışan tek yol buydu, ama daha iyi, daha akıcı yollar olup olmadığını bilmiyorum.


UPDATE yukarıdaki kodu düzeltti, şimdi çalışıyor


plese olay adını düzelt
Dan

5

orientationchangeEtkinlikle çalışırken , sayfadaki öğelerin doğru boyutlarını elde etmek için bir zaman aşımına ihtiyacım vardı, ancak matchMedia iyi çalıştı. Son kodum:

var matchMedia = window.msMatchMedia || window.MozMatchMedia || window.WebkitMatchMedia || window.matchMedia;

if (typeof(matchMedia) !== 'undefined') {
  // use matchMedia function to detect orientationchange
  window.matchMedia('(orientation: portrait)').addListener(function() {
    // your code ...
  });
} else {
  // use orientationchange event with timeout (fires to early)
  $(window).on('orientationchange', function() {
    window.setTimeout(function() {
      // your code ...
    }, 300)
  });
}

3

Doğru cevabın zaten gönderildiğine ve kabul edildiğine inanıyorum, ancak kendimi deneyimlediğim ve bazılarının burada bahsettiği bir sorun var.

Belirli platformlarda, pencere boyutları ( window.innerWidth, window.innerHeight) ve özellik gibi çeşitli özellikler window.orientationetkinliğin "orientationchange"tetiklendiği zamana kadar güncellenmez . Çoğu zaman, mülkiyet window.orientationolduğu undefinedateşlenmesinden sonra birkaç milisaniye "orientationchange"(en azından iOS'teki Chrome içindedir).

Bu sorunu ele almanın en iyi yolu şuydu:

var handleOrientationChange = (function() {
    var struct = function(){
        struct.parse();
    };
    struct.showPortraitView = function(){
        alert("Portrait Orientation: " + window.orientation);
    };
    struct.showLandscapeView = function(){
        alert("Landscape Orientation: " + window.orientation);
    };
    struct.parse = function(){
        switch(window.orientation){
            case 0:
                    //Portrait Orientation
                    this.showPortraitView();
                break;
            default:
                    //Landscape Orientation
                    if(!parseInt(window.orientation) 
                    || window.orientation === this.lastOrientation)
                        setTimeout(this, 10);
                    else
                    {
                        this.lastOrientation = window.orientation;
                        this.showLandscapeView();
                    }
                break;
        }
    };
    struct.lastOrientation = window.orientation;
    return struct;
})();
window.addEventListener("orientationchange", handleOrientationChange, false);

Yönün tanımsız olup olmadığını veya yönlendirmenin algılanan son yönlendirmeye eşit olup olmadığını kontrol ediyorum. İkisinden biri doğruysa, on milisaniye beklerim ve sonra yönlendirmeyi tekrar ayrıştırırım. Yönlendirme uygun bir değerse, showXOrientationişlevleri çağırırım . Yön geçersizse, kontrol fonksiyonumu her seferinde on milisaniye bekleyerek döngüye devam etmeye devam edeceğim.

Şimdi, genellikle yaptığım gibi bunun için bir JSFiddle yaparım, ancak JSFiddle benim için çalışmıyor ve başkaları aynı sorunu bildirmediği için destek hatası kapatıldı. Başka biri bunu bir JSFiddle'a dönüştürmek istiyorsa, lütfen devam edin.

Teşekkürler! Umarım bu yardımcı olur!


İlk testte bir sorun gördüm: Cihazım fiziksel olarak bir portre olarak yönlendirilmiş olsa bile birkaç kez saat yönünde döndürdüm ve bir uyarı "Yatay Yönelim: 180" dedi.
MarsAndBack

2

İşte yaptığım:

window.addEventListener('orientationchange', doOnOrientationChange);

function doOnOrientationChange()
{
      if (screen.height > screen.width) {
         console.log('portrait');
      } else {
         console.log('landscape');
      }
}

2

Her ne kadar soru sadece PhoneGap ve iOS kullanımıyla ilgili olsa da ve daha önce cevaplanmış olmasına rağmen, 2019'da JS ile ekran yönünü algılama sorusuna birkaç nokta ekleyebilirim:

  1. window.orientationözelliği kullanımdan kaldırılmıştır ve Android tarayıcıları tarafından desteklenmemektedir.Yönlendirme hakkında daha fazla bilgi sağlayan daha yeni bir özellik var screen.orientation. Ancak yine de deneysel ve iOS Safari tarafından desteklenmiyor . Yani muhtemelen ikisinin birleşimini kullanmak gerekir iyi sonucu elde etmek için: const angle = screen.orientation ? screen.orientation.angle : window.orientation.

  2. Sözü @benallansmith gibi onun comment , window.onorientationchangeolay öncesinde tetiklenir window.onresizeEğer orientationChange olaydan sonra bazı gecikme eklemek sürece ekranın gerçek boyutlarını almazsınız böylece.

  3. Eski mobil tarayıcıları desteklemek için bir Cordova Ekran Yönlendirme Eklentisi var, ancak bugünlerde kullanılmasına gerek olmadığını düşünüyorum.

  4. Bir screen.onorientationchangeolay da vardı, ancak kullanımdan kaldırıldı ve kullanılmamalıdır. Sadece cevabın bütünlüğü için eklendi.

Benim kullanım durumumda, gerçek yönelimi çok umursamadım, aksine pencerenin asıl genişliği ve yüksekliği, yönelimle açık bir şekilde değişiyordu. Bu yüzden olay ve pencere boyutlarını gerçekleştirme resizearasındaki gecikmelerle orientationchangeuğraşmamak için olay kullandım:

window.addEventListener('resize', () => {
  console.log(`Actual dimensions: ${window.innerWidth}x${window.innerHeight}`);
  console.log(`Actual orientation: ${screen.orientation ? screen.orientation.angle : window.orientation}`);
});

Not 1: EcmaScript 6 sözdizimini burada kullandım, gerekirse ES5'e derlediğinizden emin olun.

Not 2: window.onresizeolay yalnızca sanal yön değiştirildiğinde değil, yalnızca yön değiştiğinde de tetiklenir .


1

Cihaz yatay yönde olup olmadığını tespit etmek için bu kodu buldum ve bu durumda "siteyi görmek için yönünü değiştirmek" diyerek bir açılış sayfası ekleyin. İOS, android ve windows telefonlarda çalışıyor. Bunun oldukça zarif olduğu ve mobil site için bir manzara görünümü ayarlamaktan kaçındığı için çok yararlı olduğunu düşünüyorum. Kod çok iyi çalışıyor. Tamamen tatmin edici olmayan tek şey, birisi yatay görünümde olan sayfayı yüklerse, açılış sayfasının görünmemesidir.

<script>
(function() {
    'use strict';

    var isMobile = {
        Android: function() {
            return navigator.userAgent.match(/Android/i);
        },
        BlackBerry: function() {
            return navigator.userAgent.match(/BlackBerry/i);
        },
        iOS: function() {
            return navigator.userAgent.match(/iPhone|iPad|iPod/i);
        },
        Opera: function() {
            return navigator.userAgent.match(/Opera Mini/i);
        },
        Windows: function() {
            return navigator.userAgent.match(/IEMobile/i);
        },
        any: function() {
            return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
        }
    };
    if (isMobile.any()) {
        doOnOrientationChange();
        window.addEventListener('resize', doOnOrientationChange, 'false');
    }

    function doOnOrientationChange() {
        var a = document.getElementById('alert');
        var b = document.body;
        var w = b.offsetWidth;
        var h = b.offsetHeight;
        (w / h > 1) ? (a.className = 'show', b.className = 'full-body') : (a.className = 'hide', b.className = '');
    }
})();
</script>

Ve HTML: <div id="alert" class="hide"> <div id="content">This site is not thought to be viewed in landscape mode, please turn your device </div> </div>


1
if (window.DeviceOrientationEvent) {
    // Listen for orientation changes
    window.addEventListener("orientationchange", orientationChangeHandler);
    function orientationChangeHandler(evt) {
        // Announce the new orientation number
        // alert(screen.orientation);
        // Find matches
        var mql = window.matchMedia("(orientation: portrait)");

        if (mql.matches)  //true
    }
}

-2

Aşağıdakiler benim için çalıştı:

function changeOrientation(){
switch(window.orientation) {
case 0: // portrait, home bottom
case 180: // portrait, home top
 alert("portrait H: "+$(window).height()+" W: "+$(window).width());       
 break;
          case -90: // landscape, home left
          case 90: // landscape, home right
        alert("landscape H: "+$(window).height()+" W: "+$(window).width());
            break;
        }
    }

 window.onorientationchange = function() { 
            //Need at least 800 milliseconds
            setTimeout(changeOrientation, 1000);
        }

Zaman aşımı ihtiyacım vardı çünkü değeri window.orientationhemen güncellenmiyor


-3

İPhone için PhoneGap'te bir jQTouch uygulaması oluşturuyorum. Günlerdir bu konuyla mücadele ediyorum. Eventlistener çözümünün birkaç kez önerildiğini gördüm, ancak işe yaramadı.

Sonunda farklı bir çözüm buldum. Temel olarak settimeout kullanarak gövdenin genişliğini periyodik olarak kontrol eder. Genişlik 320 ise yön dikey, 480 ise yatay olur. Ardından, yönlendirme son kontrolden bu yana değiştiyse, bir portre öğesi işlevi veya her bir yönlendirme için işinizi yapabileceğiniz bir yatay malzeme işlevi tetikler.

Kod (not, kodda bazı tekrarlar olduğunu biliyorum, sadece henüz kesmek için rahatsız etmedim!):

// get original orientation based on body width
deviceWidth = $('body').width();
if (deviceWidth == 320) {
    currentOrientation = "portrait";
}
else if (deviceWidth == 480) {
    currentOrientation = "landscape";
}

// fire a function that checks the orientation every x milliseconds
setInterval(checkOrientation, 500);

// check orientation
function checkOrientation() {
    deviceWidth = $('body').width();
    if (deviceWidth == '320') {
        newOrientation = "portrait";
    }
    else if (deviceWidth == '480') {
        newOrientation = "landscape";
    }
    // if orientation changed since last check, fire either the portrait or landscape function
    if (newOrientation != currentOrientation) {
        if (newOrientation == "portrait") {
            changedToPortrait();
        }
        else if (newOrientation == "landscape") {
            changedToLandscape();
        }
        currentOrientation = newOrientation;
    }
}

// landscape stuff
function changedToLandscape() {
    alert('Orientation has changed to Landscape!');
}

// portrait stuff
function changedToPortrait() {
    alert('Orientation has changed to Portrait!');
}

8
Cihazı 320 veya 480 olarak sabit olarak kodlamak, gelecekte veya mevcut yüksek çözünürlüklü telefonlarla çalışmayacaktır.
Fresheyeball

1
1) onresize500 milisaniyede değil, hemen tetiklenecek bir olay kullanmalısınız 2) Bu kod android'e özgüdür, onorientationchangebunun yerine iPhone 3 için kullanın ) Tarayıcıda desteklenip desteklenmediğini test edin:"onorientationchange" in window
Dan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.