[HTML5] スマホの縦向き/横向きを検知する

特にがっつり遊ぶタイプのスマホゲームでは、端末を横にして遊ぶことが多いと思います。電車内などで立ちながら利用されることの多いニュース系のアプリやコンテンツは大抵の場合横向きですよね。今回はスマホの向きを検知し、見た目を変化する方法についてメモします。

スマホの回転検知

サンプル

以下のページから実際のサンプルを実行できます。iOSやAndroidが動作するスマホか、PC上で動作するシミュレーターなどでお試しください。 miku3.net

  • 端末を回転させると向きによって背景色が変化します。
    • 横向きの場合は「青」
    • 縦向きの場合は「橙(ダイダイ)」
  • 合わせて以下の情報も回転される度に更新されます
    • 端末の角度
    • 解像度(width x height)

ソースコード

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>HTML5 端末の向きチェック</title>
<style>
html, body{
  height: 100%;
  margin: 0px;
  -webkit-text-size-adjust: 100%;  /* Safari対策 */
}
#result{
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  border: 1px solid gray;
  font-size: 100%;
}

/* 横向き */
#result.landscape{ background-color:lightblue; }

/* 縦向き */
#result.portrait{ background-color:lightsalmon; }
</style>
</head>
<body>

<!-- 結果表示 -->
<div id="result"></div>

<script>
/**
 * [Event] ロード完了 (onload)
 */
 window.onload = ()=>{
  setResult();
}

/**
 * [Event] 画面回転 (orientationchange)
 */
window.addEventListener("orientationchange", ()=>{
  setResult();
});


/**
 * 結果表示
 */
function setResult(){
  const result = document.querySelector("#result");

  // 角度を取得
  const angle = getAngle();
  if( angle.value === undefined ){
    result.innerHTML = "端末の向きを取得することが出来ませんでした";
    return(false);
  }

  // メッセージを表示
  result.innerHTML =  "<ul>"
                      +   `<li>端末の向きは「<strong>${angle.isPortrait? "縦向き":"横向き"}</strong>」です</li>`
                      +   `<li>端末の角度は「<strong>${angle.value}</strong>」です</li>`
                      +   `<li>解像度は「<strong>${window.screen.width}x${window.screen.height}</strong>」です</li>`
                      + "</ul>";

  // 縦向き
  if( angle.isPortrait ) {
    result.classList.remove("landscape");
    result.classList.add("portrait");
  }
  // 横向き
  else{
    result.classList.remove("portrait");
    result.classList.add("landscape");
  }
}

/**
 * 端末の方向を返却する
 *
 * @return {object}
 */
function getAngle(){
  // 角度を取得
  let angle = screen && screen.orientation && screen.orientation.angle;
  if ( angle === undefined ) {
    angle = window.orientation;    // iOS用
  }

  const isPortrait = (angle === 0);
  return({
          value: angle,           // 具体的な角度
     isPortrait: isPortrait,      // 縦向き
    isLandscape: ! isPortrait,    // 横向き
  });
}
</script>
</body>
</html>

解説

端末の回転イベント

画面が回転する度にorientationchangeイベントが発生するため、これを利用します。

window.addEventListener("orientationchange", ()=>{
  // 向きが変わる度に呼び出される
});

最近のSafari(iOS), Chrome(Android/iOS), FireFox(Android/iOS)などで対応しています。詳しくはCan I useを。

Safari(iOS)
iOS4.2〜
Android Browser
Android 3〜

端末が横向きか縦向きか判定

基本的にはscreen.orientation.angleを参照することで得られるのですが、iOSのSafariはwindow.orientationを参照することになります。

let angle = screen && screen.orientation && screen.orientation.angle;
if ( angle === undefined ) {
  angle = window.orientation;    // iOS用
}

で、ここに入る値もOSによって以下のように異なります。

向きiOSAndroid
0 0
-90 270
90 90

結論から言うと0であれば縦向き、0でなければ横向きと判定できます。

if( angle === 0 ){
  console.log("縦向き");
}
else{
  console.log("横向き");
}

横向きは2種類ありますので、さらにどちらか判定するにはOSによって場合分けをしてやる必要があります。

フォントサイズを固定する

特に指定しない場合、画面をクルクル回すとそれに合わせてフォントサイズが変わってしまいます。端末の解像度が変化するためなのですが、縦でも横でも同じフォントサイズで表示したい場合には、以下のタグ及びCSSを記述します。

<meta name="viewport" content="width=device-width">

<style>
html, body{
  -webkit-text-size-adjust: 100%;  /* Safari対策 */
}
</style>

viewportでwidth=device-widthを指定することで、クルクル回転して場合でも基準とする解像度を固定した上でブラウザが処理してくれます。ただしこれだけだとiOSのSafariでうまく動作しない場合があるため、CSSで-webkit-text-size-adjustプロパティの指定を行います。

参考ページ