Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
149
Help us understand the problem. What is going on with this article?

More than 3 years have passed since last update.

@tonkotsuboy_com

iOS Safariでスクロールしただけでリサイズイベントが発生する原因と対処法

iOSの標準ブラウザであるMobile Safariにおいて、「ウインドウサイズが変わった」というイベントが発生するのはどんなときだと思いますか? Mobile SafariはiPhone端末のサイズいっぱいに全画面表示されるので、縦持ち・横持ちを切り替えた時「だけ」ウインドウサイズイベントが発生する、というのは間違いです。実は、ウインドウを最初にスクロールした時にもリサイズイベントが発生します。この現象の原因と解決方法を紹介します。

スクロール時にリサイズイベントが発生するデモ

現象を確認するためにデモを準備しました。コンテンツはiPhoneの画面サイズに収まりきれないほど長く、スクロールが必要です。ウインドウリサイズイベントが発生した時に、アラートが出ます。
http://goo.gl/yWHZ3M

JavaScriptには下記の処理が定義されています。

ウインドウリサイズ時にアラートを発生
window.addEventListener("resize", function() {
   alert("ウインドウがリサイズしました。");
})

Mobile Safari (iPhone 6s、iOS 9.1.2)で最初のスクロールをしてみると、縦持ち・横持ちを切り替えていないのにリサイズした旨のアラートが表示されます。

ios_scroll.png

何故こんなことが起こるのか?

iOS 8からスクロール時にアドレスバーが自動で小さくなる仕様となりました。これにより、アドレスバーが小さくなった分だけウインドウサイズが大きくなったと見なされ、リサイズイベントが発生するようになったのです。ウインドウサイズのことを考えれば当然の挙動なのですが、「スクロールしただけでリサイズイベントが発生する」というのはデスクトップでのブラウザに慣れている人であれば違和感を感じるのではないでしょうか。

意図したとおりにリサイズイベントを取り扱うにはどうしたらいいのか?

モバイルコンテンツで、横持ち・縦持ちが変わった時のみリサイズ処理を行うには、下記のような方法があります。

対処法1:画面の横幅が変わった時のみリサイズ処理を行う

iOS、Androidの時は縦持ち・横持ちを切り替えるとは、ウインドウの横幅が変わることと同じ意味なので、横幅が変わった時のみリサイズ処理を実行する方法です。

MobileSafari対応ウインドウリサイズ時にアラートを発生
// ウインドウの横幅を保持
var currentWidth = window.innerWidth;

window.addEventListener("resize", function() {
    if (currentWidth == window.innerWidth) {
        // ウインドウ横幅が変わっていないため処理をキャンセル。
        return;
    }

    // ウインドウ横幅が変わったのでリサイズと見なす。
    // 横幅を更新
    currentWidth = window.innerWidth;
    alert("ウインドウがリサイズしました。");
});

http://jsrun.it/tonkotsuboy/qrVDにデモを用意しました。iOS、Androidの時は縦持ち・横持ちを切り替えた時のみ、デスクトップブラウザではウインドウのりサイズ時にアラートが表示されます。

対処法2:モバイルでは端末の向きが変わった時のみリサイズ処理を行う

iOS、Androidでは端末の向きが変わった時にorientationchangeというイベントが発生します。モバイルではこのイベントが発生した時のみ、リサイズ処理を実行する方法です。

モバイルの時は端末の向きを監視する方法
// ユーザーエージェントの判別
var userAgent = navigator.userAgent;

// スマートフォンの場合はorientationchangeイベントを監視する
if (userAgent.indexOf("iPhone") >= 0 || userAgent.indexOf("iPad") >= 0 || userAgent.indexOf("Android") >= 0)
    window.addEventListener("orientationchange", resizeHandler);
else
    window.addEventListener("resize", resizeHandler);

function resizeHandler() {
    alert("ウインドウがリサイズしました。");
}

http://goo.gl/ariHN0にデモを用意しました。こちらも期待の動作をします。

Mobile Safariでリサイズ処理を扱う時は気をつけましょう

モバイルコンテンツでファーストビュー全体にコンテンツを表示してJavaScriptで処理を行いたい時等にこの現象が問題になります。この挙動を頭に入れておきましょう。

149
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
149
Help us understand the problem. What is going on with this article?