N高ネットコース2年の @YukiMihashi です。
この記事は N高等学校 (1) Advent Calendar 2020 の15日目の記事です。
CSSアニメーションで遊びながら制作した Webクリスマスカード 2020 の解説をしていきます。
本当は100%CSSと書きたいところですが、手紙の内容が時間によって変わるという仕組みや、モーダルウィンドウ表示の仕組みの簡略化のため、一部JavaScriptを使用しています…
概要
手紙やツリーのイラストがあり、クリックするといろいろ起こる、というWebのクリスマスカードです。アニメーションなので実際に見てみてください。(PC推奨ですが、スマホサイズでも動きます。IE対応はしておりません)
GitHub レポジトリ: https://github.com/yuki384/christmas-2020/
作品ページ: https://yuki384.github.io/christmas-2020/
アニメーションの実装
3種類のアニメーションがありますが、すべてCSSで実装しています。
飾りがゆれるアニメーション
まずはじめに、ベルや丸い形の飾りなどが左右に揺れるアニメーションを解説します。
animation
を使えば、ずっと見た目を動かすことができます。アニメーションが何割まで進んだタイミングで動かすか、どのように動かすか、などが指定できるので、表現の幅はかなり幅広いですね。
CSSは以下のようになっています。
#kazari {
transform-origin: 140px 700px; /* 回転の中心を設定 */
animation: rotate 2s ease-in-out -1s infinite alternate; /* アニメーションを再生 */
}
@keyframes rotate {
0% {transform: rotate(6deg);} /* 角度を変える */
100% {transform: rotate(-6deg);} /* 角度を変える */
}
回転
角度を変えるにはtransform: rotate();
を使いました。アニメーションの動きなどを設定するには、@keyframes
を使います。ここでは単に初めと終わりを設定しているだけですが、細かくタイミングを設定することもできます。
CSSのコード
@keyframes rotate {
0% {transform: rotate(6deg);}
100% {transform: rotate(-6deg);}
}
アニメーション
CSSのanimation
を使用し、先程書いたゆらゆらと左右に回転するアニメーションを再生します。すべて時間をバラバラに調整することで、揺れが不自然になりません。ここではinfinite
でずっと揺らしていますが、一回のみの再生とすることもできます。
CSSのコード
#kazari {
animation: rotate 2s ease-in-out -1s infinite alternate;
}
回転の中心を合わせる
このままだとtransform: rotate();
の中心がずれてしまっているので、transform-origin
を設定します。これは回転させながらxとyの値を微調整していくしかありませんね。
CSSのコード
#kazari {
transform-origin: 140px 700px;
animation: rotate 2s ease-in-out -1s infinite alternate;
}
これで、飾りが左右に揺れるようになりました。
プレゼントが震えるアニメーション ₍₍⁽⁽🎁₎₎⁾⁾
次に、ツリーの下にあるプレゼントが震えるアニメーションを解説します。
CSSアニメーションは何秒かおきに再生する、ということがJavaScriptのようにはできないので、工夫しました。
0%から85%の間は動かさず(同じ値を設定する)、85%~100%の間に動くようにしています。あとは、animation-delay
やanimation-duration
を調整して、程よい動きにしましょう。
#present {
animation: yure 5s ease-in-out infinite alternate;
}
@keyframes yure {
0% {transform: translate(2px);}
85% {transform: translate(2px);}
90% {transform: translate(-2px);}
95% {transform: translate(2px);}
100% {transform: translate(-2px);}
}
手紙が開くアニメーション
最後に、手紙が開くアニメーションの解説をします。
HTMLは以下のようになっています。checkbox
があるのは、checkboxがチェックされているかどうかで手紙の表示・非表示を切り替えているためです。
手紙はこのcheckbox
の<label>
となっているので、クリックで表示される、という仕組みです。
SVGの<g>
要素は、他のSVG要素をグループ化するものです。ここでは、手紙の上部分のパスを<g>
でまとめ、そのタグに id
を設定しています。
<input type="checkbox" id="text-check">
<div class="text">(手紙の内容)</div>
<div class="letter">
<label for="text-check">
<svg 省略> 省略 <g id="letter-top"> 省略 </g> 省略 </svg>
</label>
</div>
この時点では、こうなります。クリックしても、✅が切り替わるだけです。
そこで、見た目をつけていきます。
CSSは以下になります。
#text-check {
display: none; /* チェックボックスは非表示に */
}
#letter-top {
transition: all .6s; /* 状態変化のスピードを設定 */
transform-origin: 0 6%; /* 回転の中心を設定 */
}
#text-check:checked ~ .letter #letter-top {
transform: rotateX(180deg) rotateZ(2deg); /* チェック時の角度を設定 */
}
細かい解説をします。
チェックボックスは非表示にする
チェック状態で要素の状態を切り替える(後述)だけなので、見た目的には不要です。
CSSのコード
#text-check {
display: none;
}
回転する
チェックボックスがチェックされている時は、そのあとにある.letter
という要素の子要素#letter-top
を回転する、というCSSを書きます。
「チェックされている時」は疑似セレクター :checked
で、兄弟要素は一般兄弟結合子(~
) で、指定しています。
3次元の回転であるrotateX()
, rotateZ()
を使ってリアルな回転の動きを再現します。
また、先程のゆらゆら揺れる飾りと同じように、回転の中心を設定しました。
CSSのコード
#letter-top {
transform-origin: 0 6%;
}
#text-check:checked ~ .letter #letter-top {
transform: rotateX(180deg) rotateZ(2deg);
}
スピードを設定する
今回は動きの実装でanimation
を使わないため、状態が変化するときのスピードをtransition
で設定することで、アニメーションしているような見た目をつくります。
CSSのコード
#letter-top {
transition: all .6s;
}
おまけ: モーダルウィンドウの実装
今回はアニメーションについて主に解説したので、手紙クリック時の文章のモーダルウィンドウの実装についての説明は軽くにしておきます。
最後に解説した手紙と同じように、checkbox
を使って、チェック状態であれば表示、でなければ非表示、とします。閉じるための要素とトリガーとなる要素をそれぞれ<label>
にすれば、簡単に実装が可能です。
ちなみに、プレゼントなどの飾りをクリック→イラスト表示 の流れはCSSではなく、JavaScriptで実装しました。
おまけ: イラスト→SVG
これは技術とはちょっと異なりますが…イラストを書いた方法です。
気になった方が入れば参考にしてください🔽
- コンビニで買ったSALASAというボールペンで自由に書く
- それをiPhoneで撮影しコントラスト等いじって白黒画像にする
- Adobe Illustratorで「画像トレース」する
- 「ライブペイント」で色を付ける
- SVG書き出しをする
まとめ
以上、CSSアニメーションを使った簡単な実装例の紹介でした。このように、CSSでも様々な動きをつけることができます。
今回ご紹介したのはシンプルなものですが、CSSの世界に興味を持っていただけたら幸いです。
GitHub レポジトリ: https://github.com/yuki384/christmas-2020/
作品ページ: https://yuki384.github.io/christmas-2020/