JSとCSSで雪を降らせるエフェクトを実装する方法

冬のキャンペーンサイトなどに使えそうな、雪を降らせるエフェクトを作ってみたので、実装方法を紹介しようと思います。

  • jQueryなし
  • プラグインなし
  • コピペですぐに使える

CSSとJavaScriptを使って自作していきますので、ぜひ参考にしてみてください。

目次

雪を降らせるエフェクトのDEMOページ

まずはDEMOページから今回の実装内容を確認してください。

  • 一定時間ごとに雪を自動生成
  • 雪のサイズはランダム
  • 雪の発生位置はランダム

という仕様になっています。

【コピペ用】雪を降らせるエフェクトの実装コード

まずはコピペしてすぐに使いたい方のために全コードをまとめましたので、ぜひご利用ください。

index.html style.css main.jsをそれぞれ作成し、コピペすることで使えるようになっています。

もし同じ背景画像を使いたい場合は、Pixabayのこちらのページからダウンロード可能です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Snow Effect DEMO</title>
  <link rel="stylesheet" href="style.css"><!-- CSS読み込み -->
</head>
<body>
  <div class="snow-container">
    <!-- ここにコンテンツを入れる -->
  </div>
  <script src="main.js"></script><!-- JS読み込み -->
</body>
</html>
/* ===== 雪を表示するコンテナのスタイル ===== */
.snow-container {
  position: relative;
  height: 100vh; /* コンテナの高さ */
  width: 100%; /* コンテナの横幅 */
  overflow: hidden;
  background-color: #000; /* コンテナの背景 */
}

/* ===== 雪のスタイル ===== */
.snow {
  background-color: #fff; /* 雪の色 */
  border-radius: 50%;
  position: absolute;
  animation: animate-snow 10s linear;
}

/* ===== 雪のアニメーション ===== */
@keyframes animate-snow {
  0% {
    opacity: 0;
    top: 0;
  }

  10% {
    opacity: 1;
  }

  90% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    top: 100vh;
  }
}
window.addEventListener('DOMContentLoaded', ()=> {
  // コンテナを指定
  const container = document.querySelector('.snow-container');

  // 雪を生成する関数
  const createSnow = () => {
    const snowEl = document.createElement('span');
    snowEl.className = 'snow';
    const minSize = 5;
    const maxSize = 10;
    const size = Math.random() * (maxSize - minSize) + minSize;
    snowEl.style.width = `${size}px`;
    snowEl.style.height = `${size}px`;
    snowEl.style.left = Math.random() * 100 + '%';
    container.appendChild(snowEl);

    // 一定時間が経てば雪を消す
    setTimeout(() => {
      snowEl.remove();
    }, 10000);
  }

  // 雪を生成する間隔をミリ秒で指定
  setInterval(createSnow, 100);
});

次でコードの解説をしていきますので、コードを理解したい方・カスタマイズしたい方はぜひ目を通してください。

雪を降らせるエフェクトの実装手順とコードの解説

まずはHTML, CSS, JavaScriptそれぞれの役割を説明しておきますね。

  • HTMLで雪を表示するコンテナを作る
  • CSSで雪の見た目とアニメーションを設定する
  • JSで雪をランダムサイズで生成してDOMに追加する

次で実際のコードを見ながら解説していきます!

HTMLで雪を表示するコンテナを作る

<div class="snow-container">
  <!-- ここにコンテンツを入れる -->
</div>

まずは雪を降らせるコンテナを用意しましょう。

snow-containerというクラスが付いたdivタグを作成します。

このコンテナの背景に雪を降らせるので、中には好きなコンテンツを入れてください。

CSSで雪の見た目とアニメーションを設定する

/* ===== 雪を表示するコンテナのスタイル ===== */
.snow-container {
  position: relative;
  height: 100vh; /* コンテナの高さ */
  width: 100%; /* コンテナの横幅 */
  overflow: hidden;
  background-color: #000; /* コンテナの背景 */
}

/* ===== 雪のスタイル ===== */
.snow {
  background-color: #fff; /* 雪の色 */
  border-radius: 50%;
  position: absolute;
  animation: animate-snow 10s linear;
}

/* ===== 雪のアニメーション ===== */
@keyframes animate-snow {
  0% {
    opacity: 0;
    top: 0;
  }

  10% {
    opacity: 1;
  }

  90% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    top: 100vh;
  }
}

これがCSS全体ですが、少し長いので、

  • 雪を表示するコンテナのスタイル
  • 雪のスタイル
  • 雪のアニメーション

これらに分けて説明していきますね。

雪を表示するコンテナのスタイル

.snow-container {
  position: relative;
  height: 100vh; /* コンテナの高さ */
  width: 100%; /* コンテナの横幅 */
  overflow: hidden;
  background-color: #000; /* コンテナの背景 */
}

まずは雪を降らせるコンテナのスタイルから行います。

heightwidthは、中に入れる要素に合わせて調整してください。

position: relativeは、雪の粒をposition: absoluteで絶対位置指定するために必要です。

ここではrelativeを指定していますが、static以外の値ならなんでもOKです。

overflow: hiddenは、コンテナからはみ出た雪を非表示にするために必要なので、必ず設定してくださいね。

雪のスタイル

.snow {
  background-color: #fff; /* 雪の色 */
  border-radius: 50%; /* 雪を丸くする */
  position: absolute;
  animation: animate-snow 10s linear;
}

続いて雪の粒のスタイルを見ていきましょう。

雪の色を変更したければ、background-colorの値を変えてください。

animationの部分でanimate-snowを設定していますが、次はこれを作成していきます。

雪のアニメーション

@keyframes animate-snow {
  0% {
    opacity: 0;
    top: 0;
  }

  10% {
    opacity: 1;
  }

  90% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    top: 100vh;
  }
}

最後に、雪が降るアニメーションを指定しましょう。

DEMOページを見てみると、雪には次の2つのアニメーションがかかっているのが確認できますね。

  • 雪が上から下に移動
  • 開始時にフェードインし、終了時はフェードアウト

この2つはどうやって指定しているのかを見ていきます。

雪を上から下に移動させるアニメーションを設定

雪を上から下に降らせるようなアニメーションは、topプロパティを操作することで実装しています。

キーフレームの中のtopの値に注目してください。

0% {
  top: 0;
}

100% {
  top: 100vh;
}

アニメーション開始時はtop: 0、終了時にはtop: 100vhとなっていますね。

これは、コンテナの一番上からスタートし、100vh分下に移動するという指示になります。

今回はコンテナの高さが100vhのため、ここのtopの値も100vhにしましたが、実際に使うときはコンテナの高さによって値を変えてください。

開始時にフェードインさせ、終了時はフェードアウトさせる

フェードイン・フェードアウトは、opacityの値を調整することで実装しています。

0% {
  opacity: 0;
}

10% {
  opacity: 1;
}

90% {
  opacity: 1;
}

100% {
  opacity: 0;
}

まず開始時と終了時はopacity: 0を指定しているので、透明で見えない状態ですね。

アニメーション開始から10%が経過するまでに徐々に不透明にしていくことで、フェードインの効果を実装しています。

同じように、アニメーションが90%進んだ時点から終わりにかけて透明にしていくことで、フェードアウトさせています。

これでCSSは完成ですので、最後にJavaScriptを見ていきましょう。

JavaScriptでランダムサイズの雪を自動生成してDOMに追加する

window.addEventListener('DOMContentLoaded', ()=> {
  // ①雪を発生させるコンテナを指定
  const container = document.querySelector('.snow-container');

  // ②雪を生成する関数
  const createSnow = () => {
    const snowEl = document.createElement('span');
    snowEl.className = 'snow';
    const minSize = 5;
    const maxSize = 10;
    const size = Math.random() * (maxSize - minSize) + minSize;
    snowEl.style.width = `${size}px`;
    snowEl.style.height = `${size}px`;
    snowEl.style.left = Math.random() * 100 + '%';
    container.appendChild(snowEl);

    // 一定時間が経てば雪を消す
    setTimeout(() => {
      snowEl.remove();
    }, 10000);
  }

  // ③雪を生成する関数を一定間隔で呼び出す
  setInterval(createSnow, 100);
});

こちらがJavaScriptの全体のコードになります。

  • ①雪を発生させるコンテナを指定
  • ②雪を生成する関数を定義
  • ③雪を生成する関数を一定間隔で呼び出す

この3つに分けて解説していきますね。

①雪を発生させるコンテナを指定

const container = document.querySelector('.snow-container');

まずは雪を表示するコンテナを取得しましょう。

querySelectorsnow-containerのクラスが付いたdivタグを指定します。

②雪を生成する関数を定義

// ②雪を生成する関数
const createSnow = () => {

  // 1. spanタグを生成しsnowクラスを付与
  const snowEl = document.createElement('span');
  snowEl.className = 'snow';

  // 2. 雪の最小・最大サイズを指定
  const minSize = 5;
  const maxSize = 10;

  // 3. 指定した最小・最大サイズの間でランダムな数値を取得
  const size = Math.random() * (maxSize - minSize) + minSize;

  // 4. 取得したランダムな数値を雪のwidth, heightに指定
  snowEl.style.width = `${size}px`;
  snowEl.style.height = `${size}px`;

  // 5. 雪のX軸方向の発生位置をランダム指定
  snowEl.style.left = Math.random() * 100 + '%';

  // 6. コンテナに雪を追加する
  container.appendChild(snowEl);

  // 7. 一定時間が経てば雪をDOMから削除
  setTimeout(() => {
    snowEl.remove();
  }, 10000);
}

続いて、雪を生成する関数を定義していきましょう。

関数の中では、

  1. spanタグを生成しsnowクラスを付与
  2. 雪の最小・最大サイズを指定
  3. 指定した最小・最大サイズの間でランダムな数値を取得
  4. 取得したランダムな数値を雪のwidth, heightに指定
  5. 雪のX軸方向の発生位置をランダム指定
  6. コンテナに雪を追加する
  7. 一定時間が経てば雪をDOMから削除

これだけの処理が行われています。

②-1. spanタグを生成しsnowクラスを付与
const snowEl = document.createElement('span');
snowEl.className = 'snow';

雪の要素はHTMLタグのspanで実装するので、createElementでspanタグを生成します。

この空のspanタグに、CSSの段階で作成しておいたsnowクラスを付与します。

.snow {
  background-color: #fff; /* 雪の色 */
  border-radius: 50%;
  position: absolute;
  animation: animate-snow 10s linear;
}

↑こちらのクラスですね。

しかしこの段階では横幅・縦幅が指定されていないので、画面上で見ることはできません。

②-2. 雪の最小・最大サイズを指定
const minSize = 5;
const maxSize = 10;

ここでは、雪の要素の最小サイズ・最大サイズを指定します。

minSizeに最小サイズを、maxSizeに最大サイズの数値を入れてください。

DEMOでは、雪のサイズは最小5px、最大10pxとしてあります。

②-3. 指定した最小・最大サイズの間でランダムな数値を取得
const size = Math.random() * (maxSize - minSize) + minSize;

Math.random()は、0以上1未満の乱数を返す関数です。

この関数と、設定した最小値・最大値を使用することで、指定した範囲内でランダムな数値を取得することができます。

個のランダムな数値は雪のサイズに指定したいので、sizeという変数に格納しておきましょう。

②-4. 取得したランダムな数値を雪のwidth, heightに指定
snowEl.style.width = `${size}px`;
snowEl.style.height = `${size}px`;

②-3で取得したランダムな数値を、雪の要素のwidth ,heightに指定します。

これでランダムサイズの雪を生成することができました。

②-5. 雪のX軸方向の発生位置をランダム指定
snowEl.style.left = Math.random() * 100 + '%';

CSSパートで、雪の要素にはtop: 0を指定しましたね。

これで雪はコンテナの上から発生することになりますが、ここではX軸方向、つまり水平線上の発生位置を指定します。

まずは先程使用したMath.random()関数を使用して、0以上100未満のランダムな数値を取得。

この数値に%の単位をつけてleftプロパティにセットすることで、X軸上の雪の発生位置を指定することができます。

leftの数値が0%に近いほど左側になり、100%に近いほど右側になりますね。

これで雪の発生位置をバラけさせることができました。

これで雪の要素は完成です!

②-6. コンテナに雪を追加する
container.appendChild(snowEl);

②-5までで雪の要素は完成ですが、まだDOMに追加されていないため見ることができません。

雪を表示するには、完成した雪の要素をコンテナに追加する必要があります。

JavaScriptの一番最初で、雪を降らせるコンテナsnow-containerを取得しましたね。

appendChildを使って雪の要素snowElをコンテナに追加することで、ようやく雪が画面上に表示されるようになりました。

②-7. 一定時間が経てば雪をDOMから削除
setTimeout(() => {
  snowEl.remove();
}, 10000);

アニメーションが終わったら雪は見えなくなるため、削除しておきましょう。

ここでは、雪の発生から1000ミリ秒後 = 10秒後に雪を削除する処理を行っています。

ここの時間は、CSSで設定したanimationの実行時間と同じにしておきましょう。

.snow {
  animation: animate-snow 10s linear;
}

CSSでアニメーションの実行時間を10秒にしてあるので、ちょうどアニメーションが終わったタイミングで削除します。

これで雪を生成する関数は終わりです!

③雪を生成する関数を一定間隔で呼び出す

setInterval(createSnow, 100);

最後に、上で作成したcreateSnow関数を呼び出すことで雪が発生するようになります。

setIntervalを使用して、一定の間隔で関数を呼び出しましょう。

ここでは100ミリ秒ごとにcreateSnowを呼び出しているため、0.1秒毎に雪を1つ生成しているということになります。

この数値を調整することで、雪を生成するスピードを変更できるので、いろいろ試してみてください。

これでコードの解説は終わりです!

【まとめ】CSSとJSで雪を降らせるエフェクトを実装しよう!

以上、JSとCSSで雪を降らせる方法を紹介しました。

jQueryのプラグインでも実装できるそうですが、自作だとカスタマイズもしやすく、軽くて使いやすいですね。

冬がテーマのサイトや冬限定のキャンペーンLPなどで使えるかと思うので、ぜひ使用してみてください。

冬以外にもいろいろなテーマで使えそうなエフェクトを紹介してますので、以下の記事もどうぞ。

よかったらシェアしてね!

コメント

コメントする

目次
閉じる