CSS animation day26 となりました。
本日は、3D表現を用いた、lines で球体を作ります。
1. 完成版
See the Pen Line Animations by hiroya iizuka (@hiroyaiizuka) on CodePen.
# 2. なぜか? [前回](https://qiita.com/duka/items/c05fc7b9bd102b7ee139) Particlesを使って、3D の球体を作りました。 なぜ球体になったかというと、rotate でランダムな角度がついた、中心からある一定の距離にある点を集めると、球になるからです。Sass のfor 文を使って、もっと別の表現ができないか、調べてみました。
3. 参考文献
SCSS loop Circles
Understanding CSS 3D transforms
4. 分解してみる
❶.
まず、マークアップします。
<!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>
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;
}

50個の円の塊ができました。
❷.
前回と同じように、transform: rotate のアニメーションを、それぞれのdiv要素につけていきます。
perspective とtransform: preserve-3d を忘れないようにしましょう。
.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));
}
}
}
}
いい感じです!
❸.
どうしたら、もっと良いアニメーションになるでしょうか?
rotate 3d について、考察しましょう。
rotate3d(数値,数値,数値,回転角度)
rotate3dは、最初の3つの値で、回転軸のベクトルを決めます。下図で、原点から、X, Y, Zの座標が交わる立方体の手前の頂点に向かって引いた線が、回転軸となります。

最初の3つの数字は、値の大きさではなく、関係性が全てです。つまり、rotate3d(5, 6, 10, 45deg)と、rotate3d(50, 60, 100, 45 deg)は、同じエフェクトになります。
一方、4つ目の数字は、回転角度を表します。
これは、言わずもがなですが、値が大きければ大きいほど、ダイナミックに動きます。
参考文献:
eleqtriq
unformed building
以上まとめると、アニメーションでrotate3D による表現をつけるときは、以下の2つを考えます。
- 最初の3つの数字をどう変えるか? (回転する軸をどうするか?)
- rotate する角度を、どうするか? (大きく動かすのか、小さく動かすのか)
自分の目指す動きを、こちら のrotate3d ジェネレーターで確かめて、実装することもできます。では、実際にやってみましょう。
❹.
@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);
}
}
}
transform: rotate3d(1, 0, 0, 180deg) で、X軸を回転軸として、画面の奥に180度分大きく動いてますね。
では、この角度をちょっとずつずらして、網の目のようにしましょう。
@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);
}
}
}
回転角度をずらすして、動きの幅をちょっとずつ変えました。
もう少し別の表現をしましょう。
@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);
}
}
}
}
keyframes の◯◯% という数字は、ease-in-out を意識して、始めと最後はゆっくり変化することを意識しました。また、アニメーションが滑らかになるように、animation timing function は、linearに設定しました。
大変面白い動きですね。
このように、rotate3d で回転軸と動きの幅(角度)をいじると、様々な表現ができます。
それでは、また明日〜