iosとandroidでは、傾きによる縦横解像度変更のイベント取得方法が違う。
HTML5Canvasで画面全体を描画している内容、これを「傾き」によって「縦横の解像度」の変更に対する「イベント」をトリガーにすることで、この現状の状態を保持し、Canvas自体を初期化しなおして、再描画前の状態で再描画させることで、あたかも「縦」「横」それぞれで、表示領域を変更させると言うことをしたいと思った。
ちなみにHTML5Canvasは面倒なことに、一度生成した解像度(width,height)これを変更することはできない。
なので、画面いっぱいに広げたHTML5Canvasに対して、スマホの「傾き」で画面が「縦・横」に切り替わったとき、普通のHTML描画の画面のように、解像度が切り替わらず、そのため、今回、この「傾き」での「縦・横」切り替えをトリガーとして、Canvasをその解像度にあわせて、再作成する必要となった次第。
と、これが、前置きの話。
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
まず、調べると便利な「イベント」を見つける。
「orientationchange」と言うイベント。
このイベントは、「傾き」によって「縦横の解像度」の変更がなされたときに呼び出されるというもの。
また「window.orientation」で実際の傾きの角度を取得することで、上記イベントとの挙動とあわせて取得すると、「縦向き」か「横向き」かを判別することができると言う「優れもの」だそうだ。
・・・・・・・・・・・・・・・・・
しかし、そんなに「世の中」は甘くない><
と言うのも、上記イベントのコンボは「ios」では「理想どおり」に「動く」けど「Android」では、理想どおりに動かない。
何故か、色々とログ入れて調べると、どうも「orientationchange」イベントは発火するけど、このときに「window.orientation」を取ると、どうも90,0,90,180と取れる値の割り当てが「Android」毎に「ばらばら」のようで、そして、致命的なのが「orientationchange」イベント内で取得した[innerWidth]や[innerHeight]は、その時の「前回の値」つまり、前回が「縦」で今回が「横」の場合、その時取得できる値は「縦」で取得されるべき値であると言うこと。
色々と調べたことの内容を記載したが、まあわかりづらくなってしまったが、要するに普通に「orientationchange」は「ios」では使えるが「Android」では使えないと言うことだ。
で、調べると、解決方法がありました。
qiita.com
で、これを元に実際に実装した内容は以下の通りです。
// タブレット端末の傾き状態を保持. // vertical : 縦向きの状態. // landscape : 横向きの状態. // none : 未検知の状態. var tabletWidthHeightMode = "none" ; // タブレット傾き検知メソッド. var functionInclination = [] ; // androidの場合. if(isAndroid()) { var defaultOrientation; // window.orientationが0または180の時に縦長であればtrue window.addEventListener("orientationchange",function() { // スクロール位置をゼロに指定. // これを行わないと、iphoneなどでは画面がずれる場合がある. pageTop() ; },false); // 初期化処理 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(); } },false); // 画面回転時に向きをチェック window.addEventListener("resize", function(){ checkOrientation(); },false); var checkOrientation = function() { 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)) { tabletWidthHeightMode = "vertical"; } else { tabletWidthHeightMode = "landscape"; } // イベントに対する追加メソッド呼び出しが要求される場合. if( functionInclination.length > 0 ) { var list = functionInclination; var len = list.length; var m = tabletWidthHeightMode; for(var i = 0; i < len; i ++) { list[i]( m ) ; } } } } } // iosの場合. else if(isIOS()) { // 現在の方向を取得. var _getWidthOrHeight = function() { if(isTablet()) { if( window.orientation == 0 || window.orientation == 180 ) { return true ; } } else { if(window.innerHeight >= window.innerWidth) { return true; } } return false ; } // 傾きのイベントを取得. window.addEventListener("orientationchange",function( e ) { // スクロール位置をゼロに指定. // これを行わないと、iphoneなどでは画面がずれる場合がある. pageTop() ; // 傾き情報を算出. if( _getWidthOrHeight() ) { tabletWidthHeightMode = "vertical" ; } else { tabletWidthHeightMode = "landscape" ; } // イベントに対する追加メソッド呼び出しが要求される場合. if( functionInclination.length > 0 ) { var list = functionInclination; var len = list.length; var m = tabletWidthHeightMode; for(var i = 0; i < len; i ++) { list[i]( m ) ; } } },false); } // 傾き検知用メソッドの追加. // func : 傾き検知用のメソッドを設定します. // このメソッド呼び出しに対して、第一引数に[width]と設定された場合は横向きです. // このメソッド呼び出しに対して、第一引数に[height]と設定された場合は縦向きです. // ※また、この内容はタブレット端末で、縦横検知がサポートされているブラウザ専用です. // 戻り値 : trueの場合、正しく登録されました. var addInclinationFunction = function( func ) { if( typeof( func ) == "function" ) { removeInclinationFunction(func); functionInclination[functionInclination.length] = func ; return true ; } return false ; } // 傾き検知用メソッドの削除 // func : 傾き検知用のメソッドを設定します. // このメソッド呼び出しに対して、第一引数に[width]と設定された場合は横向きです. // このメソッド呼び出しに対して、第一引数に[height]と設定された場合は縦向きです. // ※また、この内容はタブレット端末で、縦横検知がサポートされているブラウザ専用です. // 戻り値 : trueの場合、正しく登録されました. var removeInclinationFunction = function( func ) { if( typeof( func ) == "function" ) { var len = functionInclination.length; for(var i = 0; i < len; i ++) { if(functionInclination[i] == func) { functionInclination.splice( i,1 ) ; return true; } } } return false ; } // 傾き検知用メソッドの全クリア. var clearAllInclinationFunction = function() { functionInclination = []; }
※上記での[isAndroid]や[isIOS]や[isTablet()]は、各自で用意してみてください^^
あと、この実装を使っていて、別件で困ったこととして、Androidの場合、傾きではなく、ブラウザサイズの変更をトリガーとしているが、このトリガー条件だと「テキスト入力」などで利用する「ソフトウェアキーボード」これが下から「ぬぬー」って感じで出てくるけど、このタイミングでも、傾き検知の「トリガー」が走ってしまう><
そんな「些細な」問題もあるので「要注意」ですw