はじめまして、
Ameba事業本部 teens事業部でフロントエンドディベロッパーをしている
2012年入社の山内と申します。

業務では、スマホ限定デコれるホムペ!Candyと新規アプリのHTML/CSSでの運用と開発を担当しています。

今回は、最近のSNSアプリでよく見ることが出来る、いいねボタンなどのアニメーションについて、CSS3アニメーションを用いて心地良い動きを実現していく方法を紹介します。

技術としては目新しくないかもしれませんが、
非常に短い時間の中でアニメーションのストーリーを組み立てたり、アニメーションを考える上で少しでも参考になればと思います。

ポヨン!プルン!という動き

今回は下記のイメージのような2つの動きについて書いていきます。

1. ポヨンとオブジェクトが正面方向に拡大して縮小するまでの動き


2. プルンとオブジェクトがバネのように震える動き


この2つのアニメーションを作る上で意識しなければならないことは、バネのように加速度が付いた動きを如何に実現するかという所にあります。初速が速くてだんだんとゆっくりになったり、初速が遅くて徐々に速くなるなどそのような動きをCSS3アニメーションを用いて制作していきます。

1. ポヨンとオブジェクトが正面方向に拡大して縮小するまでの動き

1つめの動きについて見ていきます。
このアニメーションのストーリーを見ていくと、

アニメーションエリアをタップ(またはクリック)すると、
アニメーションさせるオブジェクトが勢い良く拡大し、
その後、バウンスしながら縮小拡大し、
本来のアニメーションエリアと同じサイズになって終了するというストーリーです。

1. バウンスの表現
2. モーションのスピードとサイズ

が重要となります。

これらの事を踏まえて記述したCSSのアニメーション部分のみを抜き出すと以下のようになります。(記載したCSSコードでは、-webkit-, -moz-などのベンダープレフィックスは省略させていただきます。)

.anim-symbol {
  background-image: url("anim-symbol-on.png");
  background-size: 27px 22px;
  animation: anim-scale 0.5s ease-out;
  transform-origin: 50% 50%;
}

@keyframes anim-scale {
  0% { transform: scale(0.4, 0.4); }
  40% { transform: scale(1.2, 1.2); }
  60% { transform: scale(1, 1); }
  80% { transform: scale(1.1, 1.1); }
  100% { transform: scale(1, 1); }
}

ここでのポイントは@Keyframesの設定です。

順番にまずanimationプロパティを見ていきます。

0.5秒という短い時間の中でアニメーションさせ、ease-outでアニメーションがゆっくりと終了するように設定します。また、アニメーションさせるオブジェクトの軸を、transform-origin: 50% 50%;でオブジェクトの中央に設定します。

animation: anim-scale 0.5s ease-out;
transform-origin: 50% 50%;

次に、ポイントでもある@keyframes内の具体的なアニメーションの内容を見ていきます。

ここではオブジェクトを拡大縮小させてバウンスしているようなアニメーションを作るため、
transform: scale( ); を用いて拡大縮小のサイズを記述していきます。

まず、0%から40%の間で最初の勢い良く拡大する部分を記述します。
拡大したら40%から60%の間で縮小し、
縮小したら60%から80%の間で再度拡大、
最後に80%から100%の間で縮小して、
オブジェクトがアニメーションエリアと同じサイズになって定着し終了となります。

@keyframes anim-scale {
  0% { transform: scale(0.4, 0.4); }
  40% { transform: scale(1.2, 1.2); }
  60% { transform: scale(1, 1); }
  80% { transform: scale(1.1, 1.1); }
  100% { transform: scale(1, 1); }
}

このように0.5秒という短い時間の中で、
@keyframes内に4つの細かな動きを記述することで、
拡大縮小するバウンスの動きを実現しています。

2. プルンとオブジェクトがバネのように震える動き

さて、先程は正面方向にバウンスする動きを見てきましたが、
次はバネのように上下に震えるような動きについて見ていきます。
CSSのアニメーション部分は以下のようになります。

.anim-balloon {
  animation: anim-rotate 2s ease-out 2s infinite;
  transform-origin: 0 40%;
}

@keyframes anim-rotate {
  0% { transform: rotate(0deg); }
  10% { transform: rotate(-6deg); }
  20% { transform: rotate(7deg); }
  35% { transform: rotate(-3deg); }
  50% { transform: rotate(3deg); }
  65% { transform: rotate(-1deg); }
  80% { transform: rotate(1deg); }
  95% { transform: rotate(0deg); }
  100% { transform: rotate(0deg); }
}

先ほどのアニメーションとの違いは、
animationプロパティ内でinfiniteを指定し、繰り返しアニメーションするようにしている点と、
アニメーションさせるオブジェクトの軸を左上から、下方に40%ずらしている部分となります。

animation: anim-rotate 6s ease-out 2s infinite;
transform-origin: 0 40%;

@keyframes内をでは、上下方向にプルンとオブジェクトを震わせるため、
transform: rotate( ); を用いてオブジェクトを回転させる角度を調整します。

最初はプラス方向とマイナス方向に振れ幅を大きくし、
徐々にその値を小さくして、最終的に値を0にすることで、
加速度が付いたような動きを表現します。

また、ジワジワと動きが小さくなる部分を表現するため、0% ~ 100%間のアニメーションが進行していくタイミングを細かに調整してリアルな動きを表現しています。

.@keyframes anim-rotate {
  0% { transform: rotate(0deg); }
  10% { transform: rotate(-6deg); }
  20% { transform: rotate(7deg); }
  35% { transform: rotate(-3deg); }
  50% { transform: rotate(3deg); }
  65% { transform: rotate(-1deg); }
  80% { transform: rotate(1deg); }
  95% { transform: rotate(0deg); }
  100% { transform: rotate(0deg); }
}

このようなanimationプロパティと@Keyframesのセットを複数組み合わせることによって、
よりバリエーションの高いモーションを作ることが可能です。

ストーリーと動きの観察

ここまではCSSを用いて細かなアニメーションを記述する際の手法について書いて来ました。

しかし、先に紹介したようなCSSを記述するためには、
「オブジェクトをどのようにアニメーションさせるか?」
「それが何秒でアニメーションするのか?」
「最終的にどのように終了させるか?」
などアニメーションのストーリーをしっかりと組み立てることが重要です。

また、「バウンス」や「拡大縮小」「不透明度」の設定など、
よりリアルなアニメーションを実現するためには、
現実世界の物体の動きをよく観察して、
それに「如何に近づけていくか、どこまでマネできるか」ということが重要となってきます。

私たち人間は生活の中で、
視覚的に何が心地良くて何に違和感を感じるのかを、
暗黙の内にしっかりと認識しています(個人差はあります)。

PCやスマートフォンなどのデバイス上で、ユーザーに良質な体験を与えていくためにも、現実世界の動きの細かな部分をよく観察し、
それをアニメーションとして精緻に応用していくことが大切です。

最後に

普段の生活の場面 1つひとつを振り返ってみると、
私たちの身の回りは面白い動きで溢れています。

「ボールが弾んだり、放物線を描く描写」
「風船が膨らんだり縮んだりする様子」
「お風呂の排水口に水が吸い込まれていく様子」
などなど

応用によっては、
世の中にまだ無い、新しいアニメーションを作ることができるかもしれません!
私も常に目を光らせて見付けていきます。

最後までお読みいただきありがとうございました。