[JavaScript] スマホのフルスクリーンコンテンツ

2013/09/19

こんにちは。きんくまです。

スマホ向け、フルスクリーンコンテンツを作るときの個人的なメモです。

フルスクリーンの定義はいろいろとあると思いますが、
今回想定した条件は

・ウインドウに対して、コンテンツの高さが足りても足りなくてもよい(=スクロールが発生してもしなくてもよい)
・横スクロールなし、縦スクロールのみ
・ヘッダーフッターメニューが画面に対してposition:fixedでついている

といったものです。

作ってて、画面中央に何かを表示したいときの座標を求めるときに、正確な値を取得する方法がよくわからなかったので、やってみようと思いました。

・ウインドウの幅・高さ
・コンテンツの幅・高さ

がわかれば、中央ぞろえを計算することができます。

そのとき、どのプロパティがどういうものかを実際にデモを作って調べてみました。

検証用のhtml

mobile_fullscreen_sample

すんごく個人用なので、display:noneに書き換えたりしながら検証しました。

<!doctype html>
<html lang="jp">
<head>
<meta charset="utf-8">
    <meta
    name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0">
    <script src="src/js_libs/jquery-1.8.3.min.js"></script>
<style>
    html{
        width:100%;
        height:100%;
        background: #770000 url(images/xxxxx.gif);
        margin: 0px;
        padding: 0px;
    }
    body{
        width:100%;
        height:100%;
        background: #0d3349;
        margin: 0px;
        padding: 0px;
        font-family: sans-serif;
        font-size: 12px;
        -webkit-text-size-adjust: 100%;
    }
    #wrapper{
        width:100%;
        position: relative;
    }
    #header_bar{
        width:100%;
        height:40px;
        background: #ffcaca;
        position: fixed;
        top:0px;
        left:0px;
        z-index: 200;
    }
    #footer_bar{
        width:100%;
        height:40px;
        background: #ffff4f;
        position:fixed;
        bottom:0px;
        left:0px;
        z-index:100;
        /*display:none;*/
    }
    #contents{
        width:100%;
        background: #C5BFB3;
        position:absolute;
        top:0px;
        left:0px;
    }
    #log_area{
        padding:60px 5px 10px 5px;
    }
    h3{
        font-size:14px;
        margin-bottom:30px;
    }
    p{
        font-size:24px;
        line-height: 200%;
        margin:0px 0px 20px 0px;
    }
    #is_resize{
        font-size:12px;
    }
    #text_content{
        /*display: none;*/
        padding-bottom:60px;
    }
</style>
<script>
function log(s){
    var logArea = $('#info');
    logArea.html(s);
}

//http://james.padolsey.com/javascript/get-document-height-cross-browser/
function getDocHeight() {
    var D = document;
    return Math.max(
    D.body.scrollHeight, D.documentElement.scrollHeight,
    D.body.offsetHeight, D.documentElement.offsetHeight,
    D.body.clientHeight, D.documentElement.clientHeight
    );
}

function logCurrentRect(){
    var logText = [];
    logText.push('bodyW ' + $('body').width() + ', ' + 'bodyH ' + $('body').height());
    logText.push('docW ' + $(document).width() + ', ' + 'docH ' + $(document).height());
    logText.push('docW2 ' + document.body.clientWidth + ', ' + 'docH2 ' +
    getDocHeight());
    logText.push('clientW ' + document.body.clientWidth + ', ' + 'clientH ' +
    document.body.clientHeight);

    logText.push('<br>');

    logText.push('screenW ' + screen.width + ', ' + 'screenH ' + screen.height);
    logText.push('screen avail W ' + screen.availWidth + ', ' + 'screen avail H ' +
    screen.availHeight);

    logText.push('<br>');

    logText.push('winW ' + $(window).width() + ', ' + 'winH ' + $(window).height());
    logText.push('winInnerW ' + window.innerWidth + ', ' + 'winInnerH ' + window.innerHeight);
    logText.push('winOuterW ' + window.outerWidth + ', ' + 'winOuterH ' + window.outerHeight);

    logText.push('<br>');

    logText.push('scrollY ' + getScrollOffsetY());

    log(logText.join('<br>'));
}

function getScrollOffsetY(){
    var doc = document.documentElement, body = document.body;
    return (doc && doc.scrollTop  || body && body.scrollTop  || 0);
}

$(function(){
    logCurrentRect();

    var lastWinW = $(window).width();

    $(window).on('orientationchange', function(){
        logCurrentRect();
    });
    $(window).resize(function(){
        if(lastWinW != $(window).width()){
            $('#is_resize').text('===== resize !!!!! ===');
        }else{
            $('#is_resize').text('scroll????');
        }
    });

    $('body').on('touchstart', function(){
        var moveFlag = false;
        $('#is_resize').text('not resize');

        $('body').on('touchmove', function(){
            moveFlag = true;
        })
        .on('touchend', function(){
            if(moveFlag == false){
                logCurrentRect();
            }
            $('body').off('touchmove').off('touchend');
        });
    });

    $('#wrapper').width(window.innerWidth);
});
</script>
</head>
<body>
<div id="wrapper">
    <div id="header_bar">header</div>
    <div id="contents">
        contents<br>

        <div id="log_area">
            <div id="info"></div>
            <p id="is_resize"></p>
        </div>
        <div id="text_content">
        <h3>第1章</h3>
        <p>親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)</p>
        <h3>第2章</h3>
        <p>親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)</p>
        </div>
    </div>
    <div id="footer_bar">footer</div>
</div>
</body>

css

コンテンツがあふれる、あふれない場合があるので、
(スクロールするかしないか)
body, htmlにheight:100%としておく

全面に引く背景はbodyではなく、htmlの方につけるべし

=======

pcでは大丈夫だったが、スマホでは
min-height:100%は使わない方がよかった。(挙動があやしくなる)
=======

screen

screenは縦、横位置に関わらず同じ。縦位置のときのwidth, heightをとっている。

screen.width, screen.heightはステータスバー(時計や電池がのってる)なども含む、画面全部の大きさ

screen.availHeightはiOSのみ、ステータスバーをのぞいた高さが出る(20px引かれる)。androidでは同じ値が出た。

contents部分が画面サイズに収まるとき

bodyH = $(‘body’).height()
docH = $(document).height()
clientH = document.body.clientHeight

は等しい

window.outerWidth, window.outerHeightは機種によって実装がまちまち。
使わない方が良さそう。機種によって、ポイントの値でなく、ピクセル数(1pt = 2pxの場合2倍の値)になったりする。

固定されたscreenと違って、
window.width, window.heightなど、windowのプロパティは縦、横位置に対応して変化する

contents部分が画面サイズに収まらないとき

bodyH = $(‘body’).height()
docH = $(document).height()
clientH = document.body.clientHeight

bodyH, clientHが常に同じ大きさ、でもdocHよりも小さい値。(window.heightと同じ?)
docHが本当のコンテンツの高さ

window.height, window.innerHeightはAndroidでは同じ値が出てくる。ブラウザのヘッダー・フッターメニューの画面に見えている高さの合計を抜かした高さ

iOSでは違う値が出ている。
window.heightはブラウザのヘッダー・フッターメニューの合計を常に引いた高さ
window.innerHeightは実際に見えているメニュー部分の合計を引いた高さ。
もし、スクロールしてヘッダーメニューが隠れることがあれば、その分window.innerHeightの方が大きくなる。

スクロールとリサイズ

$(window).resizeは縦にスクロールするだけでイベントが発行されることがある。

またwindowのorientationchangeイベントはandroidの端末(古め)によっては、発行されないことがある。

なので、オリエンテーションイベント(縦横切り替え)を取りたいとき、resizeイベントでとると良い(かも?)

縦スクロールコンテンツの場合は、window.widthは変わることはないので、
それを記録しておいて、resizeイベントで前の状態のwindow.widthと比較、
もし違っている場合はオリエンテーションイベントと考えて良さそう。

調査結果まとめ

以上のことから

1) 現在のコンテンツの中身の高さを知りたいときは、上のgetDocHeightのメソッドか、$(document).height()で取得。
2) ブラウザのヘッダー・フッターメニューを抜いた高さを知りたいときは、window.innerHeightを使って取得。

という感じだと思われ

検証した端末

iOS ==

iPhone iOS 7
iPad iOS 6.1.3

Android ==

Galaxy Ace Android 2.2.1(スマホ)
Xperia SO-04D Android 4.0.4(スマホ)
Nexus7(2013) Android 4.3(タブレット)

参考

こちらの記事にあるも参考にしました。
>> First, Understand Your Screen

LINEで送る
Pocket

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る