投稿日:2020年3月3日

 
前回の桜の花びらが舞うアニメーション と同じように、DOM操作でCSSを書き換え、雪を降らせてみました。

 
8個の雪の結晶の画像をランダムに降らすように設定してあります。
雪の結晶はemStudio(エムスタジオ)さまから使わせていただきました。
結晶の画像の種類、サイズ、ぼかし、透明度、速度を乱数で設定し、フワフワと舞う雰囲気を表現しました。
今回はコメント付きのソースコードを掲載しておきます。
 
HTML

<div id="main__container"></div>

CSS

#main__container {
    width: 100%;
    /* ▼背景のグラデーション */
    background: -webkit-linear-gradient(top,
            #00004b 0%,
            #00004b 30%,
            #ffffff 100%);
    /* ▼横並びにする */
    display: flex;
    /* ▼幅いっぱいに均等配置 */
    justify-content: space-between;
}

JavaScript

// ▼アニメーション関数
function crystalLOfSnowAnime(target, YPixel) {
  const containerWidth = $(target).width(); //背景の幅
  const containerHeight = containerWidth * YPixel; //背景の高さ
  $(target).css('height', containerHeight + 'px'); //背景の高さ
  const styleTag = $("style"); //styleを取得

  // ▼snow回転 keyframes アニメーション
  const snowAnime = [
    "from {-webkit-transform:rotate3d(1,,1,0deg);}25%{transform:rotate3d(1,1,1,90deg);}50%{transform:rotate3d(1,1,1,180deg);}75%{transform:rotate3d(1,1,1,270deg);}to{transform:rotate3d(1,1,1,360deg);}"
  ];

  // ▼styleタグの最初にkeyframeアニメーションを追加
  styleTag.prepend("@keyframes snowAnime{" + snowAnime.join(" ") + "}");

  // ▼結晶の数分繰り返す
  for (i = 1; i <= 8; i++) { // imgタグ作成
    const img = $("<img>");
    img // imgタグに属性追加
      .attr({
        class: "snow",
        style: "position:relative; top:-100px;"
      })
      .appendTo(target); // snowプロパティ関数実行
    randomValue(img);
  }

  // ▼snowプロパティ関数
  function randomValue(ele) {
    const snowArray = [
      "xxxx01.png",
      "xxxx02.png",
      "xxxx03.png",
      "xxxx04.png",
      "xxxx05.png",
      "xxxx06.png",
      "xxxx07.png",
      "xxxx08.png"
    ]; // 画像の配列。xxxxは任意画像名

    // ▼配列から画像をランダムに取得
    const randomSnowSelect = snowArray[Math.floor(Math.random() * snowArray.length)];
    // ▼1か-1の配列
    const multiArray = [1, -1];
    // ▼結晶の数分、1か-1を取得。※後ほど乗算して左右方向を決定する
    const randomMulti = multiArray[Math.floor(Math.random() * multiArray.length)];

    const largeSize = 45; //雪の結晶の最大サイズ

    const objSize = randomNum(largeSize, 10), //サイズ値。45〜10pxでランダムに算出
      XSpeedNum = randomFloatNum(0.7, 0.3), //Xの移動量。0.7〜0.3でランダムに算出
      YSpeedNum = randomFloatNum(2, 0.6); //Y座標の移動量。2〜0.6でランダムに算出

    // ▼画像のディレクトリ。xxxxは任意ディレクトリ名
    const imgDir = "https://xxxx.net/xxxx/xxxx/xxxx/images/xxxx/";
    ele.attr("src", imgDir + randomSnowSelect); // 画像読み込み
    ele.attr('src', imgDir + randomSnowSelect); //画像読み込み
    ele.css({
      width: objSize + "px", //幅
      height: objSize + "px", //高さ
      margin: (largeSize - objSize) / 2 + "px", //マージン ※サイズ値の最大値から算出
      src: "images/" + randomSnowSelect, // 画像読み込み
      filter: blur(randomFloatNum(3, 0) + "px"), //ボカシ量。3〜0でランダムに算出
      opacity: randomFloatNum(1, 0.4).toFixed(1), //透明度。1〜0.4でランダムに算出
      animation: "snowAnime " + randomNum(10, 5) + "s linear 0s infinite" //結晶の回転アニメーション
    });

    let YNum = -largeSize, // Y座標の開始位置
      XNum = 0;

    // ▼アニメーションの繰り返し関数
    (function animeLoop() {
      const requestAnime = window.requestAnimationFrame(animeLoop);
      XNum += XSpeedNum; // 左右方向の移動量
      YNum += YSpeedNum; // 下方向の移動量
      ele.css({
        top: YNum + "px",
        left: XNum * randomMulti + "px"
      });
      // ▼Y座標がコンテナの高さを越えたらアニメーションをキャンセル
      if (YNum >= containerHeight) {
        window.cancelAnimationFrame(requestAnime);
        return randomValue(ele);
      }
    })();
  }
}

// ▼ランダムな整数を取得する関数
function randomNum(max, min) {
  const ranNum = Math.floor(Math.random() * (max + 1 - min) + min);
  return ranNum;
}

// ▼ランダム値取得関数 小数点第1位
function randomFloatNum(max, min) {
  const ranFlortNum = Math.random() * (max - min) + min;
  return ranFlortNum;
}

 
※今回もrequestAnimationFrameを使ってますが、PCに不可がかかるかも知れません。
低スペックのPCだと動作がぎこちなくなると思います。
パソコンが破損するとは思いませんが、何か問題が生じても責任は負い兼ねますのでご了承ください。
 

関連記事

]



 

Pocket