5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-02-15

CSS animation day25 となりました。
本日は、3D表現を用いた、Particle をやります。

なお、2D版も作りましたので、よろしければ前回 の記事をご参照ください。

#1. 完成版
ダウンロード (65).gif

See the Pen Particle Sphere by hiroya iizuka (@hiroyaiizuka) on CodePen.

#2. なぜか?

codrops によると、3D Particle の表現は、ページをローディングする待ち時間のアニメーションに使うと、効果的です。

確かに3D Particleは綺麗ですし、ランダムに動くのを見てても飽きないですし、楽しいですよね。いくらでも待てそうな気がします。

UX を向上させるために、こうした技術は、役に立ちそうですね!

#3. 参考文献
Particle Orb CSS
CSS 3D Particles

#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="particle-wrap"></div>
      <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: 20px;
  width: 20px;
  position: absolute;

  @for $i from 1 through 100 {
    &:nth-child(#{$i}) {
      transform: translate(random(100) * 1vw, random(100) * 1vh);
    }
  }
}
スクリーンショット 2019-02-15 15.04.32.png
❷. ここから、3D 表現をつけていきたいところですが、知識の復習をしましょう。

CSS で3D 表現をする時に、以下の3つが大事です。 

1: transform-style: preserve 3d
2: perspective
3: rotate

transform-style: preserve-3d

transform-style は、要素の子要素を、3D 空間に配置する(preserve-3d)か、平面に配置する(flat)かを決めます。立体的に見せたい要素の親要素に、transform-style を指定しましょう。

perspective

遠近感を出す手法です。値が小さいほど、広角レンズのように歪みが大きくなります。

See the Pen css transform rotate/perspective test by yoichi kobayashi (@ykob) on CodePen.

perspectiveも、立体的に見せたい要素の親要素に、指定しましょう。

rotate

StarWars の以前の記事でrotate Xの解説をしました。また、こちら のQiita 記事も大変わかりやすくまとまっております。


❸.

では、これから 3D を作りますが、ここで質問です!
3D座標空間で、中心から、ある一定距離に、点をランダムに配置すると、どんな形になるでしょうか?

・・・

そうです、球になりますね!
コードを書いて実験しましょう。

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

.container {
  width: 100%;
  height: 100vh;
  position: relative;
  transform-style: preserve-3d;
  perspective: 1000px;
}

.particle {
  position: absolute;
  margin: 50vh 50vw;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #fff;
}

@for $i from 1 through 100 {
  .particle:nth-child(#{$i}) {
    animation: rotate#{$i} 4s infinite;
  }

  @keyframes rotate#{$i} {
    100% {
      transform: rotateX((random(360) * 1deg)) rotateY((random(360) * 1deg))
                 rotateZ((random(360) * 1deg)) translateZ(200px);
    }
  }
}

ダウンロード (61).gif

球になりました!
ポイントというか、はまったところですが

animation: rotate#{$i}
keyframes rotate#{$i}というように、
for文の中でアニメーションを設定し、particle要素の一つ一つにアニメーションをつけなければなりません。いつものように、animation: rotate としてしまうと、アニメーションがうまく動かず、3時間くらいハマるので、気をつけましょう。

では、色を変え、keyframes をいじります。

styles.scss
 @for $i from 1 through 100 {
   .particle:nth-child(#{$i}) {
     animation: rotate#{$i} 4s infinite;
     background: hsl(random(360), 75%, 75%);
     width: random(15) * 1 + px;
     height: random(15) * 1 + px;
  }

  @keyframes rotate#{$i} {
    30% {
      transform: rotateY((random(360) * 1deg)) rotateZ((random(360) * 1deg))
        rotateX((random(360) * 1deg)) translateZ(300px);
    }
    50% {
      transform: rotateY((random(360) * 1deg)) rotateZ((random(360) * 1deg))
        rotateX((random(360) * 1deg)) translateZ(100px);
    }
    70% {
      transform: rotateY((random(360) * 1deg)) rotateZ((random(360) * 1deg))
        rotateX((random(360) * 1deg)) translateZ(130px);
    }
    90% {
      transform: rotateY((random(360) * 1deg)) rotateZ((random(360) * 1deg))
        rotateX((random(360) * 1deg)) translateZ(50px);
    }
    100% {
      transform: rotateY((random(360) * 1deg)) rotateZ((random(360) * 1deg))
        rotateX((random(360) * 1deg)) translateZ(600px);
    }
  }
}

ダウンロード (62).gif

いい感じです。
translateの値をいじると、こういう動きのほか、もっと別の表現もできます。

styles.scss

  @keyframes rotate#{$i} {
    30% {
      transform: rotateY((random(360) * 1deg)) rotateZ((random(360) * 1deg))
        rotateX((random(360) * 1deg)) translateZ(300px);
    }
    50% {
      transform: rotateY((random(360) * 1deg)) rotateZ((random(360) * 1deg))
        rotateX((random(360) * 1deg)) translate(300px, 600px);
    }
    70% {
      transform: rotateY((random(360) * 1deg)) rotateZ((random(360) * 1deg))
        rotateX((random(360) * 1deg)) translate(400px, 200px);
    }
    90% {
      transform: rotateY((random(360) * 1deg)) rotateZ((random(360) * 1deg))
        rotateX((random(360) * 1deg)) translateZ(50px);
    }
    100% {
      transform: rotateY((random(360) * 1deg)) rotateZ((random(360) * 1deg))
        rotateX((random(360) * 1deg)) translateZ(600px);
    }
  }

ダウンロード (63).gif

様々な表現ができて楽しいですね。

❹.
では最後に、ちょっとおまけです。
下のGIF をご覧ください。

ダウンロード (64).gif

これは、HTMLで入れ子の構造を持った親要素にアニメーションをつけて回転させたものですが、ご覧の通り、入れ子の子要素(赤い点)にもアニメーションが適応されます。

この特性を生かして、球体が、地球のようにぐるぐる回転する表現をつけましょう。

index.html
    <div class="container">
      <div class="wrapper">
        <div class="particle"></div>
        <div class="particle"></div>
        <div class="particle"></div>
                ・
          ・
          ・
         × 100 
      </div>  
    </div>
styles.scss
.wrapper {
  will-change: animation;
  animation: moveAround 4s infinite;
  transform-style: preserve-3d;
}

@keyframes moveAround {
  100% {
    transform: rotateY(360deg);
  }
}

ダウンロード (65).gif

無事、Particle が、全体的に、横に回転するようになりました。
こういう、綺麗なParticle動画が、CSS だけでできるなんて、素晴らしいですね。

では、また明日〜!

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?