More than 1 year has passed since last update.

ショッキングな出来事

以前、Qiitaに投稿した記事「モバイルブラウザで画面の縦長・横長を検出する方法を再確認してみた」にて、iOSとAndroidで画面回転時に発生するイベントの順序について触れたのですが...

iOS 8では、また変わってしまっています...

おさらい

  • iOS 7.x以前の場合は、画面リサイズが完了してから、orientationchangeresizeといったイベントが発生する。
  • Androidの場合は、orientationchangeイベント→画面リサイズ→resizeイベント、といった順序で処理が行われる。

Safari for iOS 8では

  • iOS 8では、resizeイベント発生→orientationchangeイベント発生→画面回転・リサイズの順序で処理が行われる。

そして、resizeイベントの段階ではwindow.orientationの値が回転前のままになっていたりします。orientationchangeイベントの段階では回転後の値に更新されています。

追記 (2015-11-17)

改めて、iOS Simulatorで挙動を確認してみると、どうもiOS 8.1では現象が改善されて、リサイズ→resizeイベント発生→画面回転→orientationchangeイベント発生の順序になっているようです。

window.orientationの値がresizeイベントの段階では変わっていないのは相変わらずで、iOS 9でも同様のようです。

さて、どうするか

そうなると、iOSではorientationchangeイベント、それ以外ではresizeイベントの時にwindow.orientationの値を判定する等のような対策が考えられます。前回記事のサンプルコードを次のように変えてみます。

orientation.js
var defaultOrientation; // window.orientationが0または180の時に縦長であればtrue

// 初期化処理
window.addEventListener('load', function() {
  if('orientation' in window) {
    var o1 = (window.innerWidth < window.innerHeight);
    var o2 = (window.orientation % 180 == 0);
    defaultOrientation = (o1 && o2) || !(o1 || o2);
    checkOrientation();
  }
  // もしあれば、その他Webアプリの初期化処理
}, false);

// iOSの場合とそれ以外とで画面回転時を判定するイベントを切り替える
var event = navigator.userAgent.match(/(iPhone|iPod|iPad)/) ? 'orientationchange' : 'resize';

// 画面回転時に向きをチェック
window.addEventListener(event, checkOrientation, false);
function checkOrientation () {
  if('orientation' in window) {
    // defaultOrientationがtrueの場合、window.orientationが0か180の時は縦長
    // defaultOrientationがfalseの場合、window.orientationが-90か90の時は縦長
    var o = (window.orientation % 180 == 0);
    if((o && defaultOrientation) || !(o || defaultOrientation)) {
      // ここに縦長画面への切り替え処理を記述
      console.log('portrait');
    }
    else {
      // ここに横長画面への切り替え処理を記述
      console.log('landscape');
    }
  }
}, false);