CSS animation day 43となりました。
本日も、microinteraction で使える、Loader を作っていきます。
1. 完成版
See the Pen Dodger Loading by hiroya iizuka (@hiroyaiizuka) on CodePen.
2. 参考文献
3. 分解してみる
❶.
マークアップしましょう。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="css/styles.css" />
</head>
<body>
<div class="container">
<div class="chaser"></div>
<div class="escaper"></div>
<div class="escaper"></div>
<div class="escaper"></div>
<div class="escaper"></div>
</div>
</body>
</html>
body {
margin: 0;
padding: 0;
background: #000;
}
.container {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.chaser {
background-color: hotpink;
width: 50px;
height: 50px;
margin-right: 80px;
}
.escaper {
background-color: dodgerblue;
width: 50px;
height: 50px;
margin-right: 40px;
}
これで、ピンクと青の四角形の配置が終わりました。
余談ですが、hotpink と dodgerblue (dodger: ひらりと素早く身をかわす人) っていうネーミングセンスが秀逸ですね。
❷.
アニメーションを実装します。
まず、chaser が、右に動いたり左に動いたりできるようにします。
.chaser {
background-color: hotpink;
width: 50px;
height: 50px;
margin-right: 80px;
border-radius: 5px;
animation: chase 3s ease-in-out infinite;
}
@keyframes chase {
50% {
transform: translateX(450px);
}
}
easy ですね!
次に、この迫ってくるhotpink を軽やかにかわします。
どうしたら良いでしょうか?
・・・
正解は、transform: rotate (180deg) と、transform-origin を設定することで解決します。具体例をみていきましょう。
上のGif画像には、transform: rotate(-180deg)を設定しました。
transform-origin が各々異なり、左から
1: transform-origin: center;
2: transform-origin: -50%;
3: transform-origin: 150%;
となっております。
アニメーションの起点を変えるだけで、こんなに違う動きがうまれるなんて、大変面白いですね!
それでは、アニメーションを作っていきましょう。
.escaper {
background-color: dodgerblue;
width: 50px;
height: 50px;
margin-right: 40px;
border-radius: 5px;
&:nth-child(2) {
animation: escape 1.5s ease-in-out infinite alternate;
}
&:nth-child(3) {
animation: escape2 1.5s ease-in-out infinite alternate;
}
&:nth-child(4) {
animation: escape3 1.5s ease-in-out infinite alternate;
}
&:nth-child(5) {
animation: escape4 1.5s ease-in-out infinite alternate;
}
}
@keyframes chase {
50% {
transform: translateX(450px);
}
}
@keyframes escape {
0%,
15% {
transform: rotate(0deg);
}
35%,
100% {
transform-origin: -50%;
transform: rotate(-180deg);
}
}
@keyframes escape2 {
0%,
30% {
transform: rotate(0deg);
}
50%,
100% {
transform-origin: -50%;
transform: rotate(-180deg);
}
}
@keyframes escape3 {
0%,
45% {
transform: rotate(0deg);
}
65%,
100% {
transform-origin: -50%;
transform: rotate(-180deg);
}
}
@keyframes escape4 {
0%,
60% {
transform: rotate(0deg);
}
80%,
100% {
transform-origin: -50%;
transform: rotate(-180deg);
}
}
ポイントは1つ
animation-direction: alternate
このプロパティによって、アニメーションを反転して再生することができます。
keyframesをごちゃごちゃいじる必要がないため、非常に便利ですね。
❸.
表現力をつけます。
ジャンプして、ちょっとへこむようにしましょう。
このジャンプには、以下のように動きをわけて考えます。
1: ジャンプする前のためを作る → scale で横長にする
2: ジャンプする → scale で縦長にする
3: 着地する → scaleで横長にする
タイミングについては、実際にアニメーションを動かしながら、微調整してください。
.escaper {
width: 50px;
height: 50px;
margin-right: 40px;
&:nth-child(2) {
animation: escape 1.5s ease-in-out infinite alternate;
&:before {
content: "";
position: absolute;
background-color: dodgerblue;
border-radius: 5px;
width: inherit;
height: inherit;
animation: sizeChange 1.5s ease-in-out infinite alternate;
}
}
@keyframes sizeChange {
0% {
transform: scale(1, 1);
}
15% {
transform-origin: center bottom;
transform: scale(1.4, 0.7);
}
25% {
transform-origin: center bottom;
transform: scale(0.4, 1.8);
}
40% {
transform-origin: center top;
transform: scale(1.4, 0.7);
}
65%,
100% {
transform: scale(1, 1);
}
}
いい感じです!
なお、inherit プロパティで、要素のプロパティの計算値を、親要素から引き継ぐことができます。
わざわざ値を設定しないのでいいので、便利ですね。
ジャンプする前に、神々しい力を発動しているように表現します。
@keyframes sizeChange {
0% {
transform: scale(1, 1);
}
・・・
40% {
transform-origin: center top;
transform: scale(1.4, 0.7);
box-shadow: 0px 0px 20px gold;
}
・・・
}
神々しくなりました笑
では、他の3つにも同じようなアニメーションを作り、ループ文を使って、リファクタリングをしましょう。
.escaper {
width: 50px;
height: 50px;
margin-right: 40px;
@for $i from 1 through 4 {
&:nth-child(#{$i + 1}) {
animation: escape#{$i} 1.5s ease-in-out infinite alternate;
&:before {
content: "";
position: absolute;
background-color: dodgerblue;
border-radius: 5px;
width: inherit;
height: inherit;
animation: sizeChange#{$i} 1.5s ease-in-out infinite alternate;
}
}
}
}
@keyframes chase {
50% {
transform: translateX(450px);
}
}
@keyframes escape1 {
0%,
15% {
transform: rotate(0deg);
}
35%,
100% {
transform-origin: -50%;
transform: rotate(-180deg);
}
}
@keyframes escape2 {
0%,
30% {
transform: rotate(0deg);
}
50%,
100% {
transform-origin: -50%;
transform: rotate(-180deg);
}
}
@keyframes escape3 {
0%,
45% {
transform: rotate(0deg);
}
65%,
100% {
transform-origin: -50%;
transform: rotate(-180deg);
}
}
@keyframes escape4 {
0%,
60% {
transform: rotate(0deg);
}
80%,
100% {
transform-origin: -50%;
transform: rotate(-180deg);
}
}
@keyframes sizeChange1 {
0% {
transform: scale(1, 1);
}
15% {
transform-origin: center bottom;
transform: scale(1.4, 0.7);
}
25% {
transform-origin: center bottom;
transform: scale(0.4, 1.8);
}
40% {
transform-origin: center top;
transform: scale(1.4, 0.7);
box-shadow: 0px 0px 20px gold;
}
65%,
100% {
transform: scale(1, 1);
}
}
@keyframes sizeChange2 {
0% {
transform: scale(1, 1);
}
25% {
transform-origin: center bottom;
transform: scale(1.4, 0.7);
}
35% {
transform-origin: center bottom;
transform: scale(0.4, 1.8);
}
50% {
transform-origin: center top;
transform: scale(1.4, 0.7);
box-shadow: 0px 0px 20px gold;
}
75%,
100% {
transform: scale(1, 1);
}
}
@keyframes sizeChange3 {
0% {
transform: scale(1, 1);
}
35% {
transform-origin: center bottom;
transform: scale(1.4, 0.7);
}
55% {
transform-origin: center bottom;
transform: scale(0.4, 1.8);
}
70% {
transform-origin: center top;
transform: scale(1.4, 0.7);
box-shadow: 0px 0px 20px gold;
}
85%,
100% {
transform: scale(1, 1);
}
}
@keyframes sizeChange4 {
0% {
transform: scale(1, 1);
}
45% {
transform-origin: center bottom;
transform: scale(1.4, 0.7);
}
65% {
transform-origin: center bottom;
transform: scale(0.4, 1.8);
}
80% {
transform-origin: center top;
transform: scale(1.4, 0.7);
box-shadow: 0px 0px 20px gold;
}
95%,
100% {
transform: scale(1, 1);
}
}
ついに完成しました!
このアニメーションのポイントは、transform: rotate と、transform-origin との合わせ技でしたね。
大変興味深い動きになり、特にtransform-originプロパティの無限の可能性、に心が動かされました。
それではまた明日〜