CSS animation で遊び倒す - Particle  2D  -


CSS animation day24 となりました。
今日は、バレンタインデーですね！
でもそんな世俗のイベントには興味が関係なく、今日も黙ってCSSアニメーションをします。涙

本日は、Saas を駆使し、Particle を作ります。


#1. 完成版

![ダウンロード (60).gif](https://qiita-image-store.s3.amazonaws.com/0/232715/264043c2-9f83-e9da-fcca-394314493c07.gif)

<p class="codepen" data-height="648" data-theme-id="0" data-default-tab="html,result" data-user="hiroyaiizuka" data-slug-hash="ZwMKGa" style="height: 648px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="Particle Animation">
  <span>See the Pen <a href="https://codepen.io/hiroyaiizuka/pen/ZwMKGa/">
  Particle Animation</a> by hiroya iizuka (<a href="https://codepen.io/hiroyaiizuka">@hiroyaiizuka</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

#2. 参考文献
[CSS trick: Animate to Different End States Using One Set of CSS Keyframes](https://css-tricks.com/animate-different-end-states-using-one-set-css-keyframes/)
[CSS Particle Animation](https://codepen.io/natewiley/pen/Ciwyn?editors=1100)

#3. 分解してみる

❶. 
ではまず、マークアップします。
100個の Particle　を作りましょう。

```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="css/styles.css" />

  </head>
  <body>
    <div class="container">
      <div class="particle"></div>
      <div class="particle"></div>
                ・
　　　　　　　　　 ・
　　　　　　　　　 ・
　　　　　　　　　×　100 
   </div>
  </body>
</html>
```


```styles.scss
body {
  margin: 0px;
  padding: 0px;
  background: #000;
  overflow: hidden;
}

.container {
  width: 100%;
  height: 100vh;
  position: relative;
}

.particle {
  background: #fff;
  border-radius: 50%;
  height: 30px;
  width: 30px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
```

<img width="925" alt="スクリーンショット 2019-02-14 10.10.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/232715/5b5ae519-1ee1-7900-11c1-7f56e93d5e81.png">

1個の白丸に100個の丸が重なってます。


❷.
では、Particle をどうやって、ランダムな色のParticleをランダムに配置するのでしょうか？　

ここで、SaSS が威力を発揮します。
100個のParticle　全ての色を繰り返し決めて配置するには、for 文を使いましょう。

```sass
  @for $変数名　from 開始の数値　through 終了の数値 {
                .....
   }

// ex:  @for $value from 1 through 3{
          padding: $value + px;
        } 
```

このように、Sass で繰り返し処理を行うことができます。
今回の場合、色と配置をこの処理の中で書いていきましょう。

```styles.scss

.particle {
　　　・
　　　・
　　　・
  @for $i from 1 through 100 {
    &:nth-child(#{$i}){
      transform: ~ ;
      background: ~ ;
    }
  }
}
```

1: __配置を決める、transform の中身を考えてみましょう。__ 

今回は、2D のため、X座標とY座標のことを考えます。
X 座標は、`vw` で、スクリーンサイズの幅に対する数値を設定します。

ランダムな値には、`random()メソッド`を使いましょう。random(100) で、1-100までのランダムな値を出してくれます。([こちら](https://qiita.com/tonkotsuboy_com/items/909b4073459ecaf7a435) のQiita記事がわかりやすいです。)

以上より計算は、`transform: translateX(random(100) * 1vw px)` となります。同様にYは、`transform: translateY(random(100) * 1vh px)`となります。
<br/>
2: __次に色を決める、background の中身を考えます。__

1. のアイデアを用いると 

```
background: rgb(255 * random(),255 * random(), 255 * random())
```
でOKです。(なお、random() で、0以上1未満の少数を返します。)

<img width="1033" alt="スクリーンショット 2019-02-14 16.34.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/232715/cde915c3-5f0a-b30c-ce8e-75bf6f66faaf.png">


できましたね！ただし上述のコードはやや冗長で、無駄があります。
せっかくなので、別の色の表現の仕方を学びましょう。

background-colorには、[hsl()](https://developer.mozilla.org/ja/docs/Web/CSS/background-color) があります。

これは、色相 (Hue)、彩度 (Saturation)、輝度 (Luminance / Lightness )の3つの要素からなる指定方法のことです。
今回プログラムで変化させるのは、色相です。

<img width="694" alt="スクリーンショット 2019-02-14 16.16.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/232715/daa1a2f2-23de-005c-cfbc-27e537f7ce55.png">

色相は、プログラム上では 上記の通り、0-360 の値で指定します。
したがって、random(360) と設定すれば、ランダムな色を生成できます。

彩度と輝度については、色の鮮やかさと発光具合ですが、実際の出来上がった色を見て、各々の気に入った値を設定してください。

```
background: hsl(random(360), 100%, 65%)
```

hslは、[こちら](https://qiita.com/anchoor/items/5edd2a67340770a8ca44) のQiita記事にも、詳しくのっております。

では、最終コードです。

```styles.scss
.particle {
  position: absolute;
  border-radius: 50%;
  width: 40px;
  height: 40px;

  @for $i from 1 through 100 {
    &:nth-child(#{$i}) {
      transform: translate(random(100) * 1vw, random(100) * 1vh);
      background: hsl(random(360), 100%, 65%);
    }
  }
}
```

❸.
アニメーションを設定しましょう。

```styles.scss
.particle{
   animation: move 3s ease-out infinite;
}


@keyframes move {
  0% {
    transform: translate(50vw, 50vh);
  }
}
```
![ダウンロード (59).gif](https://qiita-image-store.s3.amazonaws.com/0/232715/d5180898-8f24-9877-98fc-01033b68bacf.gif)


アニメーションが画面の中心(50vh, 50vw) から始まり、全体に広がってます。

ここで、あれ？と思った方もおられるのではないでしょうか？
100% のkeyframes が設定されておりませんね？

これを設定しないことによって、もともとセットしていた値 ( transform: translate(random(100) * 1vw, random(100) * 1vh)) が適応されます。

だから、こういう動きになるんですね。

では表現をよくするために、
animation delay と animation duration、サイズ、opacity をいじってみましょう。

```styles.scss
.particle {
  position: absolute;
  border-radius: 50%;
  animation: move ease-out infinite;

  @for $i from 1 through 100 {
    &:nth-child(#{$i}) {
      transform: translate(random(100) * 1vw, random(100) * 1vh);
      background: hsl(random(360), 100%, 65%);
      animation-duration: random(2) + s;
      animation-delay: random() * 0.2 + s;
      $size: random() * 20 + px;
      width: $size;
      height: $size;
      opacity: random() + 0.5;
    }
  }
}
```
![ダウンロード (60).gif](https://qiita-image-store.s3.amazonaws.com/0/232715/164a6ac7-56af-4767-8b0f-3aa125285a2a.gif)


綺麗ですね！
明日は、3D version を作ります。
ではまた〜！