PCガジェットはいつでも安いAmazonで!

SVGアニメーションで雪を降らせる

スタッフ厳選!日本HP おすすめパソコン

icon icon

今回はSVGアニメーションのサンプルを作ったのでその解説です。
CodePenでのデモは以下。

See the Pen snowDrop by シルルス (@ufpdxyu8mh998lt) on CodePen.


アニメーションしているのは雪を降らせているところと窓の明かりと煙突の煙です。

それぞれのアニメーションごとにまとめています。

目次

雪の部分のコードは以下。

    <div class="snow">
      <div id="outer" style=" transform: scale(2.39);transform-origin: top left;">
      </div>
    </div>

クラス「snow」の要素を作ってその中にSVG画像用の要素「outer」を配置します。

そしてJavascriptで

<script type="text/javascript">
        var num = 30;
        for (var i=0; i<num; i++){
          var mV = Math.ceil(Math.random()*12);
          var pV = Math.ceil(Math.random()*12);
          var sV = Math.ceil(Math.random()*5);
          $(".snow").append('<div class="move'+mV+' pos'+pV+' scale'+sV+' particle"></div>');
        }
      </script>

これで

snowの中に

<div class="move9 pos3 scale5 particle"></div>
<div class="move12 pos11 scale1 particle"></div>

といった要素が挿入されます。

クラスmoveに落ちていくアニメーションを設定し、クラスposで左右の位置を決定し、クラスscaleで雪の大きさを決定し、クラスparticleで円を描きます。

これにcssを設定します。

.snow{
  width:500px;
  height:400px;
  background: #003366;
  position: relative;
}
.particle{
width: 10px;
height: 10px;
border-radius: 50%;
background-color:rgba(255,255,255,0.5);
position: absolute;

}
@keyframes moveright{
0% {transform: translate(0%, 0%);position: absolute;}
100% {transform: translate(30px, 400px);position: absolute;}
}
@keyframes moveleft{
0% {transform: translate(0%, 0%);position: absolute;}
100% {transform: translate(-30px, 400px);position: absolute;}
}


.move1{
animation-name: moveright;
animation-duration: 10s;
animation-timing-function: linear;
animation-iteration-count: infinite;

}

.pos1{
left: 10%;

}

.scale1{
transform: scale(1);
}

窓の明かりはhtmlに記述したsvg要素の窓の明かりの部分の四角形をグループ化して対応します。

svgアニメーションの基本的なやり方は以前雲を作ったときのやり方を参照してください。

<g id="window">
             <rect
                style="fill:#dad8d8;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
                id="rect9175"
                width="16.331202"
                height="14.81202"
                x="21.648336"
                y="62.828339" />
             </g>

idにwindowと名付けて、グループ化します。

これをsvg要素のstyleタグの中で

#window rect {
                fill:#808080;
                animation: light 8s linear infinite;
              }
              @keyframes light {
                0% {
                  fill: #808080;
                }
                10%{
                  fill: #FFFF66;
                }
                80%{
                  fill: #FFFF66;
                }
                100%{
                  fill: #808080;
                }
              }

アニメーションさせます。

#windowの後にrectとつけてください。

四角形はパスではなくrectで記述されているのでcssでつかまえるためにはcssでrectと記述する必要があります。

煙突の煙

svg要素内の煙を表す円の部分をグループ分けします。

<g id="smoke1">
              <circle
                 style="fill:#ffffff;fill-opacity:1;stroke-width:1.05833;stroke-linecap:round"
                 id="path3565-0"
                 cx="41.397697"
                 cy="26.965473"
                 r="3.4181585" />
              </g>

id名はsmoke1です。

3つ使うのでsmoke2とsmoke3も同様にグループ化します。

そのcssは以下。

窓の明かりのときのように煙の円はid名のあとにcircleを付ける必要があります。

#smoke1 circle{
                animation: smoke 5s linear infinite,opacity 5s linear infinite;
              }
@keyframes smoke {
              0% {
                transform: translateY(0px);
              }
              98%{
                transform: translateY(-25px);
              }
              100%{
                transform: translateY(0px);
              }
            }
@keyframes opacity {
              0% {
                opacity: 0;
              }
              1%{
                opacity: 1;
              }
              98%{
                
                opacity: 0;
              }
              100%{
                opacity: 0;
              }
            }

アニメーションsmokeで上に立ち上ります。

アニメーションopacityで上に到達したら薄くなって消えます。

opacityを0%で1、100%で0としたり、100%で-25pxとすると消える瞬間に一度表示されてしまうので、現れるタイミングと消えるタイミングを微妙に調整しています。

まとめ

今回はSVG・CSSアニメーションで雪を降らせてみました。

今後も作品を制作して品揃えを増やしていきたいですね。

目次