🏯

UIコンポーネントにどうアニメーションをつけるか。transitionを使ってつける

2023/11/23に公開

ここのところ仕事でよくコンポーネントを作っている。可能ならばコンポーネントの状態変更が起こるときにアニメーションをつけて、変化が起きたことをわかりやすくしている。

ぼくがこういうことを最初にしようとしたとき、「アニメーション」という言葉でやり方を調べた。だから最初はCSSのanimationプロパティを使う方法になった。しかし今はtransitionプロパティを使う方法に書き直している。

なんで書き直しているかというと、animationプロパティを使うと初期描画時にもアニメーションが動いてしまうためだ。これを避けたければ、なんしか工夫を入れなければならない。

その工夫を考えたり入れるのが面倒だなーと調べていたらtransitionで解決できたので、その状況を順を追って書いておく。

まずanimationでアニメーションをつけてみる

MDNのCSSアニメーション記事を参考にする。

keyframesを定義してanimationプロパティに割り当てる。

keyframesにはfromとto(あるいは0~100%を使って細かく刻んでいくこともできる)でどんな状態になるかを定義する。fromを抜くと最初からtoに定義したプロパティ値が適用されるので、アニメーションとは言えないものになる。

要素の位置をコントロールするleftプロパティが変化するアニメーションを適用したクラスを定義してみる。

.block {
    top: 2px;
    position: absolute;

    &[data-on=true] {
        left: 2px;
        animation: goes_on 0.2s;
    }

    &[data-on=false] {
        left: 172px;
        animation: goes_off 0.2s;
    }
}

@keyframes goes_on {
    0% {
        left: 172px;
    }

    100% {
        left: 2px;
    }
}

@keyframes goes_off {
    0% {
        left: 2px;
    }

    100% {
        left: 172px;
    }
}

data-on属性の値を切り替える(要素をクリックすれば変わるようにコンポーネント定義側でやってある)することでアニメーションが動く。

CodeSandbox

先に書いた通り、このやリ方ではクラスがわりあてられたタイミングでアニメーションが動いてしまう。だから初期描画時に、クリックしていないのにアニメーションが動いてしまう。

transitionでアニメーションをつける

MDNの記事を参考にtransitionでアニメーションをつける。

どんなアニメーションをつけるかは、上でやったanimationプロパティと同様である。

transitionプロパティにいくつかの値を渡してやればいいが、今回は動かしたいプロパティであるleftと時間を渡す。さらにここでは、data-on属性に渡された値によってleftの値が変わるようにしておく。

.block {
    position: absolute;
    transition: left 0.2s;

    &[data-on=true] {
        left: 2px;
    }

    &[data-on=false] {
        left: 172px;
    }
}

CodeSandbox

animationプロパティを使った場合と違い、fromやtoのような値を定義していない。だから始点は状況次第で、前状況のない初期描画時にはアニメーションが動かずに初期位置に要素が表示される。あとはCSSで終点を定義しておく必要もないので、コンポーネントのstyleプロパティで適当にleftに値を渡してやればそこにアニメーションつきで動いていってくれる。

まとめ

コンポーネントの初期描画時にはアニメーションが動いてほしくない。なのでtransitionを使うことが個人的に多くなりそうである。

じゃあ一方でanimationを使うことはないかというとそんなこともない。遊びでトースターのスライドインにバウンドするようなアニメーションを入れた。このアニメーションを作った時にはkeyframesを使って「何%経過したら要素はどこまで移動する」みたいなものを定義しなければならなかった。トースターなので初期描画しておくものでもなく、任意のタイミングで呼ばれて出てきてくれればよかった。なのでanimationプロパティが適していた。

Discussion