iOSでPhonegapを使用して向きの変更を正しく検出するにはどうすればよいですか?


178

JQTouch参照資料を探しているこのオリエンテーションテストコードを以下で見つけました。これはモバイルSafariのiOSシミュレータでは正しく機能しますが、Phonegapでは正しく処理されません。私のプロジェクトは、このテストページを強制終了するのと同じ問題に直面しています。PhonegapでJavaScriptを使用して向きの変化を感知する方法はありますか?

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;
  }
}

回答:


297

これが私がすることです:

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


2019年5月の更新: MDNによればwindow.orientation、これは非推奨の機能であり、ほとんどのブラウザーでサポートされていません。イベントがされwindow.orientationに関連付けられているので、おそらく使用すべきではありません。orientationchange


3
これが、このディスカッションで私に有効な唯一の解決策です:) +1
Atadj

9
私がしましたwindow.onorientationchange = function() { setTimeout(functionName, 0); };
カーク・ストロベック

11
興味津々で、なぜsetTimeout Kirkを使用したのですか?
バックデスク

10
注意してください!これはデバイス固有です-度はデバイスの標準の向きとの違いを指します。つまり、タブレットが横向きで使用するように設計されている場合、90は縦向きモードであることを意味します。これに対する回避策として、最初にウィンドウの高さと幅をチェックして向きを保存し、orientationchangeを使用して変更がある場合はこれを更新します。
benallansmith

15
さらに、widthとheightが変更される前にorientationchangeが発生することがわかりました。そのため、widthとheightを使用して方向を正しく検出するには、少し遅延が必要です。このために、現在の向きを保存し、変化が検出されたときに、向きの変化を50ms刻みで250msまでチェックします。違いが見つかったら、それに応じてページを更新します。Nexus5では、通常150ミリ秒後に幅と高さの違いが検出されます。
benallansmith 2016

24

私が使用window.onresize = function(){ checkOrientation(); } しているcheckOrientationでは、window.orientationまたは本文の幅のチェックを使用できますが、「window.onresize」は、少なくとも私が持っていたモバイルおよびデスクトップブラウザーの大半で、最もクロスブラウザーの方法です。テストする機会。


1
これは素晴らしい点です。Web向けテクノロジを使用して開発している場合、この方法を使用すると、毎回展開/シミュレーションする代わりに、ブラウザでデバッグとテストをより簡単に行うことができます。
Matt Ray

2
これはまったく問題ありません...キーボードが表示されると、サイズが変更されます(そしてこれが唯一のケースではありません)。だから、これには大きな違いがあります!
HellBaby 14

2
@HellBabyキーボードが表示されると関数が呼び出されますが、方向検出に使用するメソッドによっては、window.orientationの場合と同様に、方向が変更されていないことが検出されます。だから私はまだ私の答えを待っています。
hndcrftd 14

1
@Raine Ipad 4でその方法を使用し、その問題の原因を変更することを余儀なくされました。だから、多分それは、すべての...のためにいくつかのデバイスのために働いたがいない
HellBaby

1
@MattRayこのようなデバイスの動作をエミュレートできる最新の開発ツールキットを使用して、向きの変更を簡単にテストできます。
kontur 2014

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

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

1
resizeイベントに添付できます。ただし、IIRCでは、これらのクエリはキーボードを上にすると正しく機能しません。
adi518

12

私はiOSとPhonegapにもかなり慣れていますが、eventListenerを追加することでこれを行うことができました。私はあなたが参照した例を使用して同じことをしました、そしてそれを機能させることができませんでした。しかし、これはトリックを行うように見えました:

// 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グループで「オリエンテーション」という用語を検索すると、幸運かもしれません。

方向を検出する方法の例として読んだ1つの例は、Pie Guy:(gamejs file)でした。それはあなたが投稿したコードに似ていますが、あなたのように...私はそれを動作させることができませんでした。

1つの注意点:eventListenerは私にとってはうまくいきましたが、これが過度に集中的なアプローチであるかどうかはわかりません。これまでのところ、これが私にとって有効な唯一の方法でしたが、より優れた、より効率的な方法があるかどうかはわかりません。


UPDATEは上記のコードを修正しました、それは今動作します


イベント名を修正してください
Dan

5

協力しながらorientationchangeイベント、私は、ページ内の要素の正確な寸法を得るためにタイムアウトを必要ですが、matchMediaは罰金を働きました。私の最後のコード:

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

正解はすでに投稿され、受け入れられていると思いますが、私自身が経験した問題や他の人がここで言及した問題があります。

特定のプラットフォームでは、ウィンドウのサイズ(window.innerWidthwindow.innerHeight)やプロパティなどのさまざまなプロパティwindow.orientationは、イベント"orientationchange"が発生するまでに更新されません。多くの場合、このプロパティwindow.orientationはのundefined起動後数ミリ秒の間です"orientationchange"(少なくともiOSのChromeの場合)。

この問題を処理するために見つけた最良の方法は次のとおりです。

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);

方向が定義されていないか、方向が最後に検出された方向と等しいかどうかを確認しています。どちらかが当てはまる場合は、10ミリ秒待ってから、もう一度方向を解析します。方向が適切な値であれば、showXOrientation関数を呼び出します。方向が無効な場合は、チェック機能をループし続け、有効になるまで毎回10ミリ秒待機します。

今、私はいつものようにJSFiddleを作成しますが、JSFiddleは私のために機能しておらず、他の誰も同じ問題を報告していないため、JSFiddleのサポートバグはクローズされました。他の誰かがこれをJSFiddleにしたい場合は、先に進んでください。

ありがとう!これが役に立てば幸いです!


ちなみに、最初のテストで問題が発生しました。時計回りに数回回転すると、デバイスが縦向きの場合でも「横向き:180」という警告が表示されました。
MarsAndBack

2

これが私がしたことです:

window.addEventListener('orientationchange', doOnOrientationChange);

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

2

この質問はPhoneGapとiOSの使用のみに言及しており、すでに回答されていますが、2019年にJSを使用して画面の向きを検出するという幅広い質問にいくつかのポイントを追加できます。

  1. window.orientationプロパティは非推奨でありAndroidブラウザーではサポートされていませんscreen.orientation。方向に関する詳細情報を提供する新しいプロパティがあります - 。ただし、それはまだ実験段階であり、iOS Safariではサポートされていません。したがって、最良の結果を得るには、おそらく次の2つの組み合わせを使用する必要がありますconst angle = screen.orientation ? screen.orientation.angle : window.orientation

  2. @benallansmithがコメントで述べたように、window.onorientationchangeイベントは前window.onresizeに発生するため、orientationchangeイベントの後に遅延を追加しない限り、画面の実際のサイズは取得できません。

  3. 古いモバイルブラウザーをサポートするためのCordova画面方向プラグインがありますが、今日は使用する必要がないと思います。

  4. screen.onorientationchangeイベントもありましたが、非推奨であり、使用すべきでありません。回答を完全にするために追加されました。

私のユースケースでは、実際の方向ではなく、ウィンドウの実際の幅と高さを気にしましたが、方向によって明らかに変化します。したがってresizeorientationchangeイベントとウィンドウディメンションの実現の間の遅延を処理することを避けるために、イベントを使用しました。

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

注1:ここではEcmaScript 6構文を使用しました。必要に応じて、必ずES5にコンパイルしてください。

注2:方向が変わったときだけでなく、仮想キーボードが切り替えられwindow.onresizeときにもイベントが発生します。


1

このコードは、デバイスが横向きかどうかを検出するために見つかりました。この場合、「向きを変更してサイトを表示してください」というスプラッシュページを追加します。iOS、Android、Windows Phoneで動作します。これは非常にエレガントで、モバイルサイトに横向きのビューを設定する必要がないため、非常に便利だと思います。コードは非常にうまく機能しています。完全に満足できない唯一のことは、誰かが横向きのビューにあるページをロードした場合、スプラッシュページが表示されないことです。

<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>

そして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

以下は私のために働きました:

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

の値がwindow.orientationすぐに更新されないため、タイムアウトが必要でした


-3

iPhone用のPhoneGapでjQTouchアプリを作成しています。私は何日もこの問題と闘ってきました。eventlistenerソリューションが数回提案されるのを見ましたが、それを機能させることができませんでした。

結局、私は別の解決策を思いつきました。基本的には、settimeoutを使用して定期的にボディの幅をチェックします。幅が320の場合、方向は縦、480の場合は横になります。次に、最後のチェック以降に向きが変わった場合は、縦長のスタッフ機能または横長のスタッフ機能のいずれかが呼び出され、それぞれの方向で作業を行うことができます。

コード(コードに繰り返しがあることは知っていますが、まだ削減する必要はありません!):

// 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
デバイスを320または480にハードコーディングすると、将来、または現在の高解像度の電話では機能しなくなります。
Fresheyeball

1
1)あなたが使用する必要がありますonresize使用して、このコードはアンドロイド固有ではありません500ミリ秒2)で、すぐに発火するイベントをonorientationchange、ブラウザでサポートされていた場合iPhone 3)試験のための代わりに:"onorientationchange" in window
ダン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.