CSS animationを学び、ノイズアニメーションを作ってみる
CSS animation を学ぶ
ポートフォリオサイトを作ろうと思った時に、せっかくならやったことのないことを学ぼうと CSS animation を勉強しています。
ただ勉強するのも、と思ったので、今回は CSS animation の簡単な紹介と、ノイズアニメーションを作ってみたいと思います。
CSS でアニメーションする方法
CSS のアニメーションは
-
transition
を使ったシンプルなアニメーション -
animation
と@keyframes
を使った複雑なアニメーション
があります。
transition を使ったアニメーション
transition
を使ったアニメーションはとてもシンプルです。
何か変化がある要素の CSS に対して transition
を設定するだけでアニメーションが実現できます。
.content {
/* widthが変動したらtransitionをする */
transition: width 1s;
height: 100px;
width: 100px;
background-color: white;
}
.width {
width: 400px;
}
This is Test
ボタンを押下したときに、 .content
クラスのついた要素に .width
クラスをつけてあげると下記のようになります。
transition
には以下のプロパティが設定できます。
プロパティ名 | どんなプロパティか | 例 |
---|---|---|
transition-property | トランジションを適用する CSS プロパティを指定する | height |
transition-duration | トランジションにかかる時間を指定する | 1s |
transition-delay | トランジション開始までの待ち時間を指定する | 1s |
transition-timing-function | トランジションの中間状態の指定 | ease(徐々に速く、徐々に遅く) |
transition
プロパティの楽なところは、中間の状態を考えなくて良いことです。
アニメーションを作るときには最初の状態から最後の状態まで、中間の状態を意識する必要があります。
transition
プロパティでは、その中間の動きを一切考える必要がないのがメリットです。
始点と終点でどのような動きになるかだけを与えてあげると、あとは中間を計算してやってくれるので、誰でも比較的なめらかな動きを表現することができます。
animation と @keyframes を使った複雑なアニメーション
transition
は便利ですが、複雑な挙動を伴うアニメーションは中間の状態が指定できないので対応できないです。
どうしても複雑なアニメーションをしたい、、、!そんな時に使えるのが animation
と @keyframes
になります。
.content2 {
height: 100px;
background-color: white;
/* animation プロパティにアニメーション、 時間、 繰り返しなどを設定する */
animation: width-animation 2s infinite;
}
@keyframes width-animation {
0% {
width: 100px;
}
100% {
width: 400px;
}
}
animation
と keyframes
を使ったアニメーションは、 @keyframes
の内部で %
を指定、アニメーションが実行される時間内での動きを指定できます。
上のアニメーションを下記のように指定してあげると、要素を伸び縮みさせることができるようになります。
@keyframes width-animation {
0% {
width: 100px;
}
25% {
width: 400px;
}
50% {
width: 200px;
}
100% {
width: 400px;
}
}
このように、transition
よりもより複雑なアニメーションを簡単に可能にするのが animation
と keyframes
になります。
keyframes の実践:ノイズを作ってみる
ここまでで一旦 CSS アニメーションについてはざっと説明したので、実際に手を動かして実践してみたいと思います。
今回は文字にノイズを走らせてみます。
ノイズの実装を考える
ノイズを走らせるにあたって、どうすれば良いか考えます。
幸いなことにモニターに接続するケーブルがいい感じに接続不良を起こして画面にノイズが走っていたので、ノイズをを観察します。
ノイズを観察した結果、重要そうな要素は
- 画面の一部がずれているような様子であること
- 規則性がなく、ひたすら不規則に乱れが起き続ける
の 2 つのようでした。
この 2 つをステップを分けてアニメーションにしていきます。
第一ステップ:ずれを作る
まずは初めに挙げた 画面の一部がずれているような様子であること
を実現してみます。
今回は ずれ
を clip-path
を使って表現したいと思います。
import type { NextPage } from 'next'
import style from '../styles/Top.module.css'
const Top: NextPage = () => {
return (
<div className={style.top_container}>
<p className={style.test} data-text="TEST">TEST</p>
</div>
)
}
export default Top
.test {
position: relative;
width: 400px;
color: white;
font-size: 100px;
}
.test::before {
/* beforeでテキスト要素を取得する */
content: attr(data-text);
position: absolute;
background-color: black;
color: white;
width: 400px;
/* clip-pathで要素をくり抜く 今回はinsetで単純な四角形とする */
clip-path: inset(55px 0 0 0);
/* 位置をずらす */
left: 2px;
}
簡単に説明すると
-
content: attr();
でdata-text
に指定した表示させる文字と同様の文字を取得 -
clip-path
で上から 55px 以下からの範囲で文字を切り抜く -
left
で文字をずらす
ということをしています。
さらにこの inset の幅を小さくしてみましょう。
.test::before {
...
/* bottomの位置を調節して、clip-pathで切り抜く要素を狭める */
clip-path: inset(55px 0 56px 0);
...
}
少しノイズらしくなりました。ここからこれをアニメーションにしていきましょう!
第二ステップ:ずれを動かして、ノイズにする
第一ステップでのずらしを @keyframes
を使うことで動的にして、ノイズっぽくします。
下記のサンプルに従って、 clip-path
を動かしてみましょう。
.test::before {
...
animation: noise-animation 2s infinite;
}
/* アニメーション本体 */
@keyframes noise-animation {
0% {
clip-path: inset(93px 0 21px 0);
}
5% {
clip-path: inset(91px 0 23px 0);
}
10% {
clip-path: inset(89px 0 25px 0);
}
15% {
clip-path: inset(93px 0 21px 0);
}
20% {
clip-path: inset(58px 0 56px 0);
}
25% {
clip-path: inset(56px 0 54px 0);
}
30% {
clip-path: inset(60px 0 54px 0);
}
35% {
clip-path: inset(56px 0 54px 0);
}
40% {
clip-path: inset(93px 0 21px 0);
}
45% {
clip-path: inset(91px 0 23px 0);
}
50% {
clip-path: inset(89px 0 25px 0);
}
55% {
clip-path: inset(93px 0 21px 0);
}
60% {
clip-path: inset(55px 0 59px 0);
}
65% {
clip-path: inset(25px 0 90px 0);
}
70% {
clip-path: inset(28px 0 88px 0);
}
75% {
clip-path: inset(32px 0 84px 0);
}
80% {
clip-path: inset(35px 0 81px 0);
}
85% {
clip-path: inset(93px 0 21px 0);
}
90% {
clip-path: inset(89px 0 25px 0);
}
95% {
clip-path: inset(82px 0 32px 0);
}
100% {
clip-path: inset(87px 0 27px 0);
}
}
ちょっと clip-path
の影響か、 before
要素に border らしきものが出てしまっていますが、ノイズらしい動きになりました!
(もしどなたか border らしきものを消せるようにできるならばコメントもらえると嬉しいです、、、!)
ちなみにさらにノイズらしくするためには after
の疑似要素も追加、別途 animation
を起こしたり、また、 text-shadow
をつけて疑似要素に色のついた影をつけるとよりノイズらしくなります。
終わりに
CSS animation は Javascript を介せずとも複雑なアニメーションを実現することができます。
まだまだ始めたばかりですが、調べれば調べるほど沼にハマるような気がしています。
皆様もぜひ CSS animation、やってみていただけると嬉しいです。
Discussion