拙作の「MMD Viewer 改」をスマホで動かした際に、
スマホ本体を回転すると何か妙なことになってしまうことに気が付きました・・・。
実は前回の投稿と絡んでいたりします。
スマホ本体を回転するとUIが小さくなってしまう
具体的には以下のような感じ。
一例としてブラウザにおける画面サイズを 360×720 としてあります。
始めの状態の縦長画面の時。
90度回転を2度やると、
何故かUIの表示が小さくなってしまいます。何故こうなるのかイマイチよく分かってないのですが、ブラウザのviewportのスケールが変わってしまうようです。
そこでスケール値を調べて見たところ、
・始めの状態の縦長画面の時 ➜ scale=1
・90度回転した後の横長画面の時 ➜ scale=1
・さらに90度回転した後の縦長画面の時 ➜ scale=0.5
という感じになっていました。2度めの回転でスケールが 360/720 = 0.5 となってしまうようです。ただ、レンダリング面であるcanvasはスケールしたりしません。なんでやろ。
なお、
回転時のスケールは以下のようなJavaScriptなコードで取得しています。orientationchange イベント後の resize イベントで取得しないとうまく行かない感じです。
var orientationChange = false;
window.addEventListener('orientationchange', function() {
orientationChange = true;
});
window.addEventListener('resize',function() {
if (orientationChange) {
orientationChange = false;
console.log('scale=',document.body.clientWidth / window.innerWidth);
}
});
スケールしないようにすれば良いのだが・・・
要するに、
スケールするから変になってしまうので、スケールしないようにしてしまえば良いはず。htmlのheadタグ内に以下のようにviewportなmetaタグを書いてやります。
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
あるいは、
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1">
でも行けます。
確かにこれで直ってくれるのですが、
当然ながらピンチ操作による画面の拡大縮小はできなくなります。「MMD Viewer 改」的には特にそれでも問題ないのですが(再生停止中は3Dな拡大縮小操作として扱われるので)、Chromeの Lighthouse でチェックすると「ユーザーがスケールできないのはよろしくない」と文句を言ってきます(^_^;) SEO的に問題なのは避けたいですね。うむぅ、どうしたら良いのだろうか。
とにかくも、
viewportなmetaタグは基本的に以下のようにするのがSEO的にも無難なようです。
<meta name="viewport" content="width=device-width,initial-scale=1">
スケールをリセットする
思案した結果、
スマホ回転時にスケールを1にリセットすれば良いのではないかという結論に至りました。そこで色々調べてみたのですが、JavaScriptからviewportのスケールを直接的に操作する手段(APIとか)が無いっぽい・・・(^_^;)
うむぅ、困りました。
ただ調べた中で、こういうのがありました。残念ながら解決策とはなっていないのですが、viewportなmetaタグを書き変えればどうにかなるんじゃね?的な事にキュピーンと閃きました!
つまり、
回転時に以下のように書き換えて強制的にスケールを1にさせ、
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1">
その後のリサイズ時に以下のように書き換えて元に戻してしまえば行けるのでないかと。
<meta name="viewport" content="width=device-width,initial-scale=1">
で、
実際にやってみた所、うまく行きました(^_^)
Chromeのデベロッパーツール、およびAndroidな自分のスマホでも期待したように行けているようです。ピンチ操作による画面の拡大縮小も可能です。ただし、iPhoneでも同様にうまく行くかどうかは確認できていません。ブラウザが Safari だとダメっぽいかも?(^_^;)
ちなみに、
JavaScriptなコードは以下のような感じになります。
var viewportMeta = document.querySelector('meta[name="viewport"]'),
orientationChange = false;
window.addEventListener('orientationchange', function() {
orientationChange = true;
// 強制的にスケールを1にする。
viewportMeta.content = 'width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1';
});
window.addEventListener('resize',function() {
if (orientationChange) {
orientationChange = false;
// 元に戻す。
viewportMeta.content = 'width=device-width,initial-scale=1';
}
});
もう一つの問題
スマホの回転とかには関係ないのですが、
別な問題がありましたのでついでにそのことについて書いてみます。
「MMD Viewer 改」では、画面下部に操作コントローラーを表示するようになっており、適時自動で隠れるように作ってあります。操作コントローラー全体を覆うdivのCSSなスタイルをいじることで隠れたりするようになっています。具体的には position:absolute;
にして、bottom
の値を書き換えることで実現しています。つまり、その値がゼロなら見えている状態、操作コントローラーの高さのマイナス値なら見えていない状態となり、適当に時間で補間してやれば隠れるようなアニメーションとなるわけです。
ただ、
スマホのブラウザのアドレスバーの有無によって、どういうわけかその高さ分だけ操作コントローラーの位置がズレてしまう現象が起こったりします。アドレスバーが存在する前提でウインドウの高さが計算され、それに引きずられる形で bottom
の値が設定されてしまうのでしょうか? なので、アドレスバーが無くなるとその分だけズレてしまう??
何故こうなってしまうのか、
イマイチよく分かっていませんが、bottom
による画面下端からの位置だとダメっぽいので、画面上端からの位置である top
の値をいじるように変更してみました。そうしたら、アドレスバーの有無に関わらず操作コントローラーの位置がズレずに期待したようになってくれました。やれやれ。
どうにもスマホとかのモバイル対応はなかなかに難しい所がありますね(^_^;)