JavaScriptやjQueryにて、スマホの画面回転時にイベントを発火させたい時にはresizeイベントが良く使われるかと思います。
しかしスマホのブラウザの仕様上、resizeイベントはスマホの縦スクロールでも発火してしまうという問題があります。
そこで、画面が回転した時だけresizeイベントを発火させる方法をまとめます。
記事の後半ではorientationchangeイベントについても少し触れます。
この記事の目次
resizeイベントがスマホの縦スクロールで発火してしまう
既にご存じかと思いますが、JavaScriptやjQueryで画面がリサイズした時に発火するイベントである「resize」を使えば、スマホの画面回転(縦横切り替え)を検知して発火させることができます。
例えばJavaScriptでは以下のようなコードです。
//resizeイベントでスマホの画面回転時に何かを処理する window.addEventListener('resize',function(){ alert("resizeイベントが発生しました。"); });
これをjQueryで書くと以下のような感じになります。
//jQueryで書いた場合はこんな感じ $(window).on('resize',function(){ alert("resizeイベントが発生しました。"); });
これだけでスマホ(iPad)の画面の回転を検知してイベントを発火させ、任意の処理を行うことができます。
ただ、上記のようにresizeイベントをそのまま使うとスマホの縦スクロールでもresizeイベントが発火してしまいます。
実際に上のコードをiPhoneの実機で確認してみると以下のような感じになります。
このようにスクロールした瞬間にresizeイベントが発火してしまいます。
resizeイベントはその名の通り、端末の画面サイズが変わった時に発火するイベントですが、スマホの場合は画面回転時だけでなく、縦スクロールでも発火します。
スマホのスクロールでresizeが発火する原因
ではなぜスマホの縦スクロールでresizeイベントが発火するのか?
この原因はスマホのブラウザの仕様にあります。
スマホでWebページを開き、縦にスクロールするとアドレスバーやメニューが出たり引っ込んだりしますが、これがスクロール時にresizeイベントが発火する原因です。
考えてみれば分かるのですが、アドレスバーやメニューを表示する領域が変更されるごとに、端末の画面サイズ(ビューポート)も“リサイズ”されているわけです。
この動きについてはiOSでもAndroidでも基本同じですが、実機でないとここまで動かないため、パソコンから確認している場合なんかだとまず気が付きません。
スマホの画面回転時だけresizeを発火する方法
スマホの画面が回転した時だけresizeイベントを発火するようにしたい場合は、少し工夫する必要があります。
具体的には画面回転前の画面サイズの横幅をあらかじめ取得しておき、resizeイベント発火時にこの横幅が変更されていれば回転したとみなすように変更すればOKです。
これはコードで見ていただいた方が分かりやすいです。
//予め画面の横幅を取得して格納しておく let lastWidth = window.innerWidth; window.addEventListener('resize',function(){ //格納しておいた横幅と現在の横幅が異なる時だけ発火させる if(lastWidth != window.innerWidth){ //変更後の横幅を再取得して更新する lastWidth = window.innerWidth; //~ここからスマホ回転時の処理~ alert("スマホ回転!"); } });
window.innerWidth
で画面の横幅だけを監視し、この幅が変更された時だけ処理を実行するようにすれば、画面回転時だけ発動させることが出来ます。
スマホ回転時の処理を関数にして分けたい時は以下を参考にどうぞ。
let lastWidth = window.innerWidth; function SP_rotate(){ if(lastWidth != window.innerWidth){ lastWidth = window.innerWidth; alert("スマホ回転!"); } } window.addEventListener('resize',SP_rotate);
画面回転時だけresizeが発火する様子
せっかくなので上のコードを実際に動かしてみた様子をGIFにしました。
少し分かりにくいですが、スクロール時にはresizeイベントが発火しなくなり、画面が回転した時はきちんと発火している様子が分かるかと思います。
resize発火時に画面の横幅を比較することで「縦→横」も「横→縦」も発動します。
これでOKなのですが、一応resize自体は連続発火しているはずなので場合によってはthrottleでresizeイベントの発火回数も抑制してあげると更に良いかもです。
orientationchangeイベントを使う方法
最後にorientationchangeイベントについてです。
このイベントは“端末の向きが変更された時”に発火するイベントです。
今まではresizeイベントで画面の回転を検知、発火していましたがorientationchangeを使えばスマホの縦スクロールでイベントが発火することはありません。
使い方は今まで触れてきたresizeと同じです。
今回のコード例ならresizeをorientationchangeに変更するだけでOKです。
window.addEventListener('orientationchange',function(){ alert("orientationchangeイベントが発生しました。"); });
上のコードをiPhoneの実機で確認すると以下のようになります。
orientationchangeなら何も工夫せずに画面の回転だけをピンポイントで拾えます。
初めからこっちを使えば良いのでは!?
というところですが、orientationchangeイベントは個人的にお勧めしません。
orientationchangeよりresizeがお勧め
スマホの画面回転時だけイベントを発火させるなら、resizeイベントを工夫して使用するよりもorientationchangeを使った方が楽なのですが、orientationchangeには色々な問題があります。
例えば、以下のサイトで対応ブラウザを確認してみると、主要ブラウザがことごとく未対応となっています。一方でresizeイベントは全ブラウザ対応です。
今回iPhoneのSafariでは先ほどのように一応動作確認できましたが、不安要素です。
外部リンク
また、orientationchangeはAndroidとiOSといったOSの違いで処理内容が微妙に違うということもあるようです。この点でもresizeは昔からあるだけあって優秀です。
orientationchangeイベントの不具合というか仕様は調べれば色々出ますので、気になる方は調べていただければと思うのですが、幅広いデバイスに対応するならresizeイベントを使う方が良いと思います。
まとめ
以上、意外と長くなってしまいましたがresizeイベントはスマホの縦スクロールでも発火するので、画面回転時のみ発火させたいなら画面の横幅なども回転の判定条件に入れましょう。
orientationchangeイベントを使えば一発ですが、全デバイスに対応というところでは少し不安要素が多いかなと思います。この記事が何かの参考になれば幸いです。
ではではこのへんで・w・