要素が拡大縮小を繰り返し・点滅するローディング画面をJavaScriptで実装してみる(備忘録)

今回はJavaScriptを用いて、ページを読み込んでいるときに要素が拡大縮小を繰り返し・点滅するローディング画面を実装してみる。

実装の前に伝えておきたいことがある。個人的にはローディング画面は好きではない。なぜかというと、ページを読む気にならなくなるからである。

ページを読み込んで何秒も待たされるのは正直ストレスが溜まる。読む側としては一刻も早く読みたいのである。

画像の読み込みが重たいようなページに対しては、有効な手段なのかもしれないが、今後は5gなどで通信速度も速くなっていくことになると思うので、ローディング画面の需要は無くなるかもしれない。

ただ、面白い視点でローディング画面からの導入をしているようなページもあるので、一概には言えない。

きちんと目的を考えて実装するかを判断するのがいいかと思う。

デモはこちら

それでは解説に入っていく。

htmlの記述について

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ローディング</title>
  <link rel="stylesheet" href="../reset.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div id="js_loading" class="bl_loading">
    <div class="bl_loadingText">loading...</div>
  </div>
  <main>
    <section>
      <div class="ly_inner" id="menu1">
        <h2>menu1</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu2">
        <h2>menu2</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu3">
        <h2>menu3</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu4">
        <h2>menu4</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu5">
        <h2>menu5</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
  </main>
  <script src="style.js"></script>
</body>
</html>

ページの中身を表示させるために、menu1〜menu5を仮テキストで入れている。

ローディング画面に関係する記述は下記にあたる。

<div id="js_loading" class="bl_loading">
  <div class="bl_loadingText">loading...</div>
</div>

JavaScript側で読み込ませるために、id(任意の名前でOK)を設定し、表示するテキストは、「loading…」とした。

cssの記述について

@charset "utf-8";

/* ==========================
  初期設定
========================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}
img {
  width: 100%;
}

/* ==========================
  ローディング画面
========================== */
.bl_loading {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #444;
  color: #fff;
  font-size: 24px;
  display: flex;
  justify-content: center;
  align-items: center;
  opacity: 1;
  visibility: visible;
  transition: 0.3s;
}
.bl_loading.loaded {
  opacity: 0;
  visibility: hidden;
}
@keyframes loading {
  50% {
    opacity: 0.3;
    transform: scale(1.1);
  }
}
.bl_loadingText {
  animation: 0.6s loading infinite;
}

/* ==========================
  コンテンツの中身
========================== */
.ly_inner {
  width: 100%;
  max-width: 1080px;
  margin: 100px auto;
  padding: 20px;
  background-color: #ccc;
}
.ly_inner h2 {
  font-size: 150%;
  font-weight: bold;
  margin-bottom: 30px;
}
.md_textblock > * + * {
  margin-top: 10px;
}

ローディング画面は、読み込まれているときは中のページが見えないよう全画面が背景色や画像で覆われていることが多い。

ローディング画面が表示されているときは、縦や横にスクロールしても表示が変わらないため、要素を固定することが求められる。

これらのことを考えて、ローディング画面が表示されている時のCSSを割り当てていく。

.bl_loading {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #444;
  color: #fff;
  font-size: 24px;
  display: flex;
  justify-content: center;
  align-items: center;
  opacity: 1;
  visibility: visible;
  transition: 0.3s;
}

positionをfixedにすることで位置を固定して、幅と高さを100%にして全画面いっぱいに表示させる。

あとは中のloading…が上下左右中央に配置されるようdisplayをflexにして、justify-contentとalign-itemsをcenterにして調整した。

opacity以下については、JavaScriptとの兼ね合いで、ローディング画面が表示されている状況を記述している。

.bl_loading.loaded {
  opacity: 0;
  visibility: hidden;
}

JavaScript側でローディング後にloadedのクラスがつくように設定しているため、その時に要素を透過させるために適用している。

@keyframes loading {
  50% {
    opacity: 0.3;
    transform: scale(1.1);
  }
}
.bl_loadingText {
  animation: 0.6s loading infinite;
}

keyframesでanimationの内容を設定し、実行するときは該当のクラスに対して、keyframesでつけたloading(任意の名前でOK)を引っ張ってくるだけでよい。

JavaScriptの記述について

'use strict';

// ローディング画面
function loadedPage() {
  const loadingID = document.getElementById("js_loading");
  loadingID.classList.add("loaded");
}
window.addEventListener('load', function () {
  setTimeout(loadedPage, 2000);
});
setTimeout(loadedPage, 5000);

まずやりたいこととしては、ページを読み込んでいるときはローディング画面を表示した状態にしておきたい。

また、コンテンツの内容によっては、ページの読み込みに時間がかかることも想定されるため、ある程度の時間が経ったら完全にページが読み込まれていない状況でも強制的にローディング画面が終わるように設定する。

今回は何度も同じ関数を宣言するのが手間なので、適当な関数を定義してから行うことにしたい。

function loadedPage() {
  const loadingID = document.getElementById("js_loading");
  loadingID.classList.add("loaded");
}

ここでloadedPage(任意の名前でOK)の関数を定義している。idをhtmlにつけたのは、ここで呼び出すために使用したかったからである。

ここでは、js_loadingに対して、loadedのクラスが追加されるという設定になっている。

これでloadedPageをいつでも呼び出すことができるようになる。

window.addEventListener('load', function () {
  setTimeout(loadedPage, 2000);
});
setTimeout(loadedPage, 5000);

loadというのは、ページが完全に読み込みが終わってからといった意味になるので、実際に実行されるのはコンテンツの中身が完全に表示されてから実行されることになる。

setTimeoutは何秒後に処理をするのかを決めることができるため、今回はページが読み込まれてから2秒後に、htmlのjs_loadingに対して、loadedのクラスが追加されるという設定になる。

また、先述したが、ページが完全に読み込まれていない場合でも5秒後には表示させたほうがいいと考え、loadとは別の箇所にsetTimeout(loadedPage, 5000);の記述をした。

これで実装完了になる。次は別のローディング画面のパターンも紹介していけたらと思う。

5 返信

コメントはクローズされています。