CSS animation で遊び倒す - loop lines 3D-

CSS animation day26 となりました。
本日は、3D表現を用いた、lines で球体を作ります。


#1. 完成版

![ダウンロード (6).gif](https://qiita-image-store.s3.amazonaws.com/0/232715/368554ff-39de-a5c3-142a-07e0fb033b2a.gif)

<p class="codepen" data-height="614" data-theme-id="0" data-default-tab="html,result" data-user="hiroyaiizuka" data-slug-hash="VgVpJx" style="height: 614px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="Line Animations ">
  <span>See the Pen <a href="https://codepen.io/hiroyaiizuka/pen/VgVpJx/">
  Line Animations </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. なぜか？
[前回](https://qiita.com/duka/items/c05fc7b9bd102b7ee139) Particlesを使って、3D の球体を作りました。
なぜ球体になったかというと、rotate でランダムな角度がついた、中心からある一定の距離にある点を集めると、球になるからです。

Sass のfor 文を使って、もっと別の表現ができないか、調べてみました。

#3. 参考文献
[SCSS loop Circles](https://codepen.io/halvves/pen/KJXpYZ?editors=1100)
[Understanding CSS 3D transforms](https://www.eleqtriq.com/2010/05/understanding-css-3d-transforms/)

#4. 分解してみる

❶. 

まず、マークアップします。

```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="line"></div>
                ・
　　　　　　　　　 ・
　　　　　　　　　 ・
　　　　　　　　　×　50 
    </div>
  </body>
</html>
```

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

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

.line {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  height: 200px;
  width: 200px;
  border-radius: 50%;
  border: 1px solid #fff;
}
```

<img width="547" alt="スクリーンショット 2019-02-16 11.27.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/232715/d3354a72-aa1d-89fd-00f0-1988a5d60fdd.png">


50個の円の塊ができました。

❷.

前回と同じように、transform: rotate のアニメーションを、それぞれのdiv要素につけていきます。
perspective とtransform: preserve-3d を忘れないようにしましょう。


```styles.scss

.container {
  width: 100vw;
  height: 100vh;
  position: relative;
  transform-style: preserve-3d;
  perspective: 2000px;
  transform: translate(40%, 30%);
}

.line {
  position: absolute;
  height: 200px;
  width: 200px;
  border-radius: 50%;
  border: 1px solid #fff;
  transform-origin: center center;

  @for $i from 1 through 50 {
    &:nth-child(#{$i}) {
      animation: move#{$i} ease 4s infinite;
    }

    @keyframes move#{$i} {
      100% {
        transform: rotateX((random(360) * 1deg)) rotateY((random(360) * 1deg))
          rotateZ((random(360) * 1deg));
      }
    }
  }
}
```

![ダウンロード (2).gif](https://qiita-image-store.s3.amazonaws.com/0/232715/9a89953f-e334-3aaf-e5e8-ba9610dc2918.gif)


いい感じです！

❸.
どうしたら、もっと良いアニメーションになるでしょうか？
rotate 3d について、考察しましょう。

```
rotate3d(数値,数値,数値,回転角度) 
```

rotate3dは、最初の3つの値で、回転軸のベクトルを決めます。下図で、原点から、X, Y, Zの座標が交わる立方体の手前の頂点に向かって引いた線が、回転軸となります。

<img width="227" alt="スクリーンショット 2019-02-16 15.16.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/232715/8dc1e65d-60d6-7a5f-4135-61f7ef7841b0.png">




最初の3つの数字は、値の大きさではなく、関係性が全てです。つまり、rotate3d(5, 6, 10, 45deg)と、rotate3d(50, 60, 100, 45 deg)は、同じエフェクトになります。


___

一方、４つ目の数字は、回転角度を表します。
これは、言わずもがなですが、値が大きければ大きいほど、ダイナミックに動きます。


参考文献:
[eleqtriq](https://www.eleqtriq.com/2010/05/understanding-css-3d-transforms/)
[unformed building](http://unformedbuilding.com/articles/learn-about-css-transforms/)



以上まとめると、アニメーションでrotate3D による表現をつけるときは、以下の2つを考えます。

1. 最初の3つの数字をどう変えるか? (回転する軸をどうするか？)
2. rotate する角度を、どうするか? (大きく動かすのか、小さく動かすのか)


自分の目指す動きを、[こちら](http://ds-overdesign.com/transform/rotate3d.html) のrotate3d ジェネレーターで確かめて、実装することもできます。では、実際にやってみましょう。

❹.

```styles.scss

  @for $i from 1 through 50 {
    &:nth-child(#{$i}) {
      animation: move#{$i} ease-in-out 3s;
    }

    @keyframes move#{$i} {
      0% {
        transform: rotate3d(0, 0, 0, 0deg);
      }
      50% {
        transform: rotate3d(1, 0, 0, 180deg);
      }  
      100% {
        transform: rotate3d(0, 0, 0, 0deg);
      }
    }
  }
```

![ダウンロード (4).gif](https://qiita-image-store.s3.amazonaws.com/0/232715/e577f8bd-ef58-2a91-ef15-7d396600095d.gif)

transform: rotate3d(1, 0, 0, 180deg) で、X軸を回転軸として、画面の奥に180度分大きく動いてますね。

では、この角度をちょっとずつずらして、網の目のようにしましょう。

```styles.scss
   
 @for $i from 1 through 50 {
    &:nth-child(#{$i}) {
      animation: move#{$i} ease 3s infinite;
    }


  $angle: 180 - $i * 1.8;

    @keyframes move#{$i} {
      0% {
        transform: rotate3d(0, 0, 0, 0deg);
      }
      50% {
        transform: rotate3d(1, 0, 0, #{$angle}deg);
      }

      100% {
        transform: rotate3d(0, 0, 0, 0deg);
      }
    }
  }
```

![ダウンロード (5).gif](https://qiita-image-store.s3.amazonaws.com/0/232715/b66aeb58-afe5-f643-27fa-1ba5b2c8fdad.gif)

回転角度をずらすして、動きの幅をちょっとずつ変えました。
もう少し別の表現をしましょう。

```styles.scss

  @for $i from 1 through 50 {
    $angle: 180 - $i * 1.8;
    &:nth-child(#{$i}) {
      animation: move#{$i} linear 3s infinite;
    }

    @keyframes move#{$i} {
      0% {
        transform: rotate3d(0, 0, 0);
      }
      40% {
        transform: rotate3d(0, -1, -1, #{$angle}deg);
      }
      50% {
        transform: rotate3d(0, -1, -1, #{$angle * 1.5}deg);
      }
      60% {
        transform: rotate3d(0, -1, -1, #{$angle * 2}deg);
      }
      70% {
        transform: rotate3d(0, -1, -1, #{$angle * 1.5}deg);
      }

      100% {
        transform: rotate3d(0, 0, 0);
      }
    }
  }
}
```

![ダウンロード (6).gif](https://qiita-image-store.s3.amazonaws.com/0/232715/b57cf187-289f-6130-7565-b1d4af939de6.gif)


keyframes の◯◯% という数字は、ease-in-out を意識して、始めと最後はゆっくり変化することを意識しました。また、アニメーションが滑らかになるように、animation timing function は、linearに設定しました。

大変面白い動きですね。

このように、rotate3d で回転軸と動きの幅(角度)をいじると、様々な表現ができます。
それでは、また明日〜