Little Strange Software

スマホアプリの開発を行う LittleStrangeSoftware のブログです。

【CSS】落下アニメーション【keyframesの復習】

 

 どうも!LSSです!!

 

このブログで、keyframesとanimationを使ったCSSアニメーションを色々試みてきました。

とっつきにくいながらも、分かってくると面白いkeyframesですが、LSSだけ分かっていても他の方が置いてけぼりだと「コードを少し変えて使いたい」時などに手をつけられない、というのがありそうです。

 

今回はこれまでに自分が理解してきたkeyframesアニメーションを、keyframes定義の内容に絞って、簡単なものから徐々に手を加えていく様子を記事にしてみました。

 

 

その1 シンプルに落下

 

 

コード

<style>
@keyframes rakka{
0%{top:0px;}
100%{top:330px;}
}
.waku{
position:relative;
width:280px;
height:400px;
background:linear-gradient(#8888ff,#ccccff 69.9%,#884444 70%);
}
.mono{
position:absolute;
width:30px;
height:30px;
background:radial-gradient(farthest-side,#ff0000 99%,transparent 100%);
left:200px;
animation:rakka 3s linear infinite;    
}
</style>
<div class="waku">
<div class="mono"> </div>
</div>

 

まず、HTMLは

<div class="waku">
<div class="mono"> </div>
</div>

として、「waku」クラスの中に「mono」クラスが入っている、という状態にしています。

 

「waku」クラスは、
.waku{
position:relative;
width:280px;
height:400px;
background:linear-gradient(#8888ff,#ccccff 69.9%,#884444 70%);
}
position:relative;」を指定した上で、幅280ピクセル、高さ400pxに。
background:linear-gradient(#8888ff,#ccccff 69.9%,#884444 70%);」で空と土を描いています。

 

「mono」クラスが落下する赤い丸で、
.mono{
position:absolute;
width:30px;
height:30px;
background:radial-gradient(farthest-side,#ff0000 99%,transparent 100%);
left:200px;
animation:rakka 3s linear infinite;    
}
こちらは「position:absolute;」、幅高さともに30ピクセルで、
background:radial-gradient(farthest-side,#ff0000 99%,transparent 100%);」で赤い丸を描いています。
そして「left:200px;」で、「(wakuクラスの中での)位置を左から200ピクセル」と指定しています。
上下位置はここでは指定せず、
animation:rakka 3s linear infinite;
で「rakka」アニメーションを3秒、無限繰り返し再生を指定しています。

 

「rakka」アニメーションは、
@keyframes rakka{
0%{top:0px;}
100%{top:330px;}
}

と定義しており、アニメーション開始時(0%)には「top:0px;」、アニメーション終了時(100%)には「top:330px;」としています。
これが、このアニメーションを呼び出している「mono」クラスに適用されるため、
「赤い丸は左から200ピクセルの位置で、上から0ピクセルの位置から330ピクセルの位置まで3秒で移動する」
という動きになるんですね。

 

 

その2 着地後静止

 

 

その1では、着地するや否や消滅して、また上からになっていました。

「地面に激突」した様子を表現するために、keyframesの内容だけ書き換えると↑のようになります。

@keyframes rakka{
0%{top:0px;}
80%{top:330px;}
100%{top:330px;}
}

80%{top:330px;}」を追加しました。

 

これにより、top(上からの距離)の値が
「経過時間0%の時は0px、経過時間80%の時は330px(0→330に徐々に変化)、80%から100%までは330pxのまま」
という動きになり、この指示に従って動いているのが上記のアニメーションとなります。

 

また、「80%{ } 」と「100%{ } 」の内容が全く同じ「top:330px;」ですが、この場合は

@keyframes rakka{
0%{top:0px;}
80%,100%{top:330px;}
}

のように書いても「80%も100%もtop:330px;」という指定になり、同じ意味合いのコードとなります。

 

今回のような「動いたり止まったり」するアニメーションを書く際には、こうやってまとめて記述する方が楽というのはありますね^^

 

 

その3 バウンド

 

 

もう少し手を加えて「着地後一度跳ね返り、途中まで上がってからまた落ちる」動きにしてみました。

これはどんなkeyframesを書いているかというと…

@keyframes rakka{
0%{top:0px;}
60%{top:150px;}
40%,80%,100%{top:330px;}
}

このようなコードで実現しています。

60%{top:150px;}」が「途中まで上がって」の状態ですね。

 

アニメーションの動きは「%」で示す進行度に従って動作しますが、今回のコードで60%より後ろに40%の指定を書いているように、「コード上は時系列順でなくても構わない」という事になります。

ただし、分かり辛くはなるので、これを「時系列順」に並べて書き直すとしたら…

@keyframes rakka{
0%{top:0px;}
40%{top:330px;}
60%{top:150px;}
80%{top:330px;}
100%{top:330px;}
}

↑このような並びになります。

 

つまり「topの値は最初0pxから一旦330pxの位置まで落下し、その後150pxの位置まで上昇。その後また330pxの位置まで落下し、経過時間80%~100%の間は330pxのまま」という指定ですね。

 

%指定は「〇%の時間が経過した時に、どうなっているか、という指定」を書く事で、それがシナリオとなります。

今は20%ごとで書いていますが、自由にもっと細かく指定する事ができるので、もっと複雑な動き(例えばバウンド回数を増やすなど)にする事もできます。

 

 

その4 ちょっとだけリアルに

 

 

少しだけ手を加えてみました。

「少し」過ぎて、「その3」とどう違うか分かり辛いかもですが…「跳ね返ってからまた落下する間の速度をゆっくりにしてみた」んですね。

コードはこちら。

@keyframes rakka{
0%{top:0px;}
50%,70%{top:200px;}
60%{top:150px;}
40%,80%,100%{top:330px;}
}

 

50%,70%{top:200px;}」を書き足しました。
こうする事により、

  • 経過時間40%時点の位置は330px
  • 経過時間50%時点の位置は200px
  • 経過時間60%時点の位置は150px
  • 経過時間70%時点の位置は200px
  • 経過時間80%時点の位置は330px

と、間の時間は均等(10%)ですが、移動距離は「130、50、50、130」と途中が半分以下の速度に落ちている事になります。

…本当は、曲線の放物線を描くような指定にするとよりリアルなのですが、思いっきり簡略化した感じです。

この%指定でより曲線的変化に近づけようとすると、コードが限りなく長くなる事になりますので妥協しました。

 

※余談ですが、keyframesを呼び出す時の指定「animation:rakka 3s linear infinite;」の「linear」部分を「ease-in-out」にするなどして曲線的な変化にする事はできます(%の進み方自体を変化させる)が…「最初と最後」を変化させるような指定で、今回のような途中を部分的にしようとすると話がとてもややこしくなります。

 

 

あとがき

keyframes定義は「経過時間の何%時点で どうなっている」を指定します。
(実際のトータル再生時間はanimationプロパティの側で指定)

 

%の間の量(時間)と、それぞれで指定した位置の差(移動距離)の割合で移動速度が決まり、また細かく指定すればするほど複雑な動作を指定する事ができます。

 

今回は「top」プロパティだけを変化させましたが、複数のプロパティを変化させる事もできるので(例:0%{top:0px;left:100px;}のように並べます)、手間とコードが長くなる事をいとわなければ凄い力作が誕生するかもですね^^

 

 

 

ってなとこで、今回はこのへんで!

次回もまた、よろしくお願いします^^