ショッキングな出来事
以前、Qiitaに投稿した記事「モバイルブラウザで画面の縦長・横長を検出する方法を再確認してみた」にて、iOSとAndroidで画面回転時に発生するイベントの順序について触れたのですが...
iOS 8では、また変わってしまっています...
おさらい
- iOS 7.x以前の場合は、画面リサイズが完了してから、
orientationchange
やresize
といったイベントが発生する。 - 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);