resizeとorientationchangeのタイミングの落とし穴
スマホの画面の向きの変更のイベント検知でよく「resize」「orientationchange」を使用すると思う。
このイベント検知を行う場合、大抵は恐らくDOMのサイズ調整とかを行うのだと思うが、それについて落とし穴があった。
これをaddEventListenerでやったときにタイミングの問題で、正常に幅や高さが取得・設定できなくなる。
例えば以下のようなコードを使用した場合。
var oc = window.addEventListener('orientationchange', function(){ height(); }); var rs = window.addEventListener('resize', function(){ height(); }); function height(){ var elm = document.getElementById('box'); var h = window.innerHeight - (window.innerHeight / 2); elm.style.height = h + 'px'; }
id=”box”の要素をresizeやorientationchangeのイベントを検知して画面の高さの半分に合わせるという非常に単純なコード。
これが、スマホで画面の縦横切り替えを何回か繰り返した際に、高さの算出が正常に行われず、変更できないパターンが出てくるときがある。
これはどうやら、イベントが検知される際に若干のタイムラグがあるためにこうなっているようだ。
縦横切り替えでの画面の回転が完了する前に計算が行われた場合、変更前のwindow.innerHeightの高さが参照されてしまう。(innerHeightの高さの参照先が他のDOMである場合も同様。)
対処法として、この現象に遭遇した場合は以下のように計算~高さ合わせの処理を遅延させてやれば問題ない。
var oc = window.addEventListener('orientationchange', function(){ setTimeout(function(){ height(); }, 100); }); var rs = window.addEventListener('resize', function(){ setTimeout(function(){ height(); }, 100); }); function height(){ var elm = document.getElementById('box'); var h = window.innerHeight - (window.innerHeight / 2); elm.style.height = h + 'px'; }
setTimeoutでカンマ1秒後の実行を指定。
遅延のタイミングが早すぎると同じ結果となってしまうので注意。