ローディング画面を作ってみる

時間がかかる処理をする時に、画面に変化がないと不安になります。
ということで、ローディング画面を作ってみます。

<!DOCTYPE html>
<html lang="ja" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title>loading scene</title>
        <link rel="stylesheet" href="style.css">
        <script type="text/javascript" src='loading.js'></script>
    </head>
    <body>
        <div class="wrap">
            <div id="_loading">
                <div id="_loadingText">now loading...</div>
            </div>
            <button type="button" id="loadingButton" name="button">読み込みボタン</button>
        </div>
    </body>
</html>
html {
    font-size: 16px;
}

.wrap {
    margin: auto;
    padding-top: 3rem;
    width: 99%;
    height: 100vh;
    background-color: #eeeeee;
    text-align: center;
}

button {
    margin: 1rem;
    min-width: 100px;
    color: #fff;
    background-color: #eb6100;
    border-bottom: 5px solid #b84c00;
    -webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, .3);
    box-shadow: 0 3px 5px rgba(0, 0, 0, .3);
}

button:hover {
    /* margin-top: 3px; */
    color: #fff;
    background: #f56500;
    border-bottom: 2px solid #b84c00;
}

#_loading {
    display: none;
    background-color: #eeeeeecc;
    position: fixed;
    width: 100%;
    height: 100vh;
    top: 0;
    left: 0;
}

#_loadingText {
    padding-top: 30%;
    font-size: 3rem;
}
window.onload = () => {
    // ローディング要素外枠の id と外枠
    const loadingOuterId = '_loading';
    const loadingOuter = document.getElementById(loadingOuterId);
    // ローディング中の描画テキスト描画用の要素 id とテキスト描画用要素
    const loadingTextId = '_loadingText';
    const loadingText = document.getElementById(loadingTextId);
    // ローディング中に描画するテキスト
    const LOADING_TEXT = 'now loading ...';
    // ローディング画面描画用のボタン
    const loadingButtonId = 'loadingButton';
    const loadingButton = document.getElementById(loadingButtonId);
    // インターバルタイマーの id
    let id = null;
    // ボタンがクリックされたらローディング画面を描画する
    loadingButton.addEventListener('click', () => {
        drawLoading();
    });
    // ローディング画面の描画関数
    const drawLoading = () => {
        // すでにタイマーを起動している場合は抜ける
        if(id !== null) return;
        loadingOuter.style.display = 'block';
        loadingText.innerHTML = '';
        // 100ms(0.1s)毎に呼び出す
        id = setInterval(() => {
            // ローディング中に描画するテキストを全て描画し終わったら、ローディング画面を非表示にする
            if(LOADING_TEXT.length === loadingText.innerHTML.length) {
                // インターバルタイマーをクリア
                clearInterval(id);
                // ローディング画面を非表示
                loadingOuter.style.display = 'none';
                id = null;
            }
            // ローディング中のテキスト
            loadingText.innerHTML = LOADING_TEXT.substring(0, loadingText.innerHTML.length + 1);
        }, 100);
    }
}

document.getElementById

HTML と JavaScript を連携するあれです。
こちらの記事にちょっと詳細が載ってます。

setInterval

今回の主役です。
一定の遅延間隔で処理を繰り返します。
for 文の遅延バージョンみたいなものです。
ただし、非同期・・・です。

id = setInterval(function() {
// time 時間毎に実行したい処理
}, time);
// time の単位は ms(1/1000) です。

1ms = 1/1000s というのは、1000ミリ秒で1秒ということになります。
loading.js 内では、100ms(0.1秒)毎に関数を呼び出しています。
また、setInterval は インターバル ID を返します。
この ID は、一意に決まっており、

clearInterval(id)

とすることで、繰り返し処理を終了できます。
setInterval をむやみやたらに使用すると、動作が重たくなります。
使用しなくなったら、clearInterval しましょう。

ローディング画面を作ってみる

使い方としては、
ローディング画面描画→時間のかかる処理→ローディング画面の非表示
となるはずです。
ということで、

const _loadingOuter = document.createElement('div');
const _outerStyle = 'display:block;background-color:#eeeeeeaa;position:fixed;width:100%;height:100vh;top:0;left:0;';
_loadingOuter.style = _outerStyle;
const _loadingText = document.createElement('div');
const _textStyle = 'padding-top:20%;font-size:3rem;text-align:center;';
_loadingText.style = _textStyle;
_loadingOuter.appendChild(_loadingText);
const _text = 'now loading ...';
let _loadingId = null;
// 読み込み画面を表示する
function drawLoading() {
    if(_loadingId !== null) return;
    document.body.appendChild(_loadingOuter);
    _loadingText.innerHTML = '';
    _loadingId = setInterval(() => {
        if(_text.length === _loadingText.innerHTML.length) _loadingText.innerHTML = '';
        _loadingText.innerHTML = _text.substring(0, _loadingText.innerHTML.length + 1);
    }, 200);
}
// 読み込み画面非表示にする
function hideLoading() {
    clearInterval(_loadingId);
    _loadingOuter.remove();
    _loadingId = null;
}

作ってみました。
コピペして読み込むとローディング画面が表示されます。
いろいろ終わって、ローディング画面を非表示にするときは、hideLoading() を呼び出してください。
Loading.js を読み込む場所は </body> タグの下にしてください。

<!DOCTYPE html>
<html lang="ja" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title>counter</title>
        <!-- ページのデザインを外部ファイルにまとめるときは CSS を使うと良き -->
        <link rel="stylesheet" href="../style.css">
        <!-- JavaScript の読み込み (HTML ファイルと JS ファイルは同じディレクトリ階層) -->
        <script type="text/javascript" src="counter.js"></script>
    </head>
    <body>
        <div class="wrap">
            <p>カウント:<span id="drawCount">0</span></p>
            <button type="button" id="countUpButton" name="button">+1</button>
            <button type="button" id="countDownButton" name="button">-1</button>
        </div>
    </body>
    <!-- ここで読み込む -->
    <script type="text/javascript" src="Loading.js"></script>
</html>

使用してみると、こんな感じになります。