• Web制作
  • sin()、cos()を、CSSアニメーションとJavaScriptで動かした時の違い

sin()、cos()を、CSSアニメーションとJavaScriptで動かした時の違い

CSS上の三角関数、sin()、cos()を動かすため、CSSアニメーションを使ってみたのですが、きちんと動きませんでした。もう少し正確にいうと、動くには動いたが、想定通りには動かなかったという感じです。

いろいろと原因を考えてみて、おそらくこういった理由なんじゃないかと思い、それをまとめてみました。とはいっても、レンダリングレベルまで見ている訳ではないので、間違っていたらゴメンナサイ。

オブジェクトを楕円形に動かすサンプル

まずは、こちらのページで、サンプルを確認してください。

sin()、cos()を、CSSアニメーションとJavaScriptで動かした時の違い

あと、こちらが動作のスクリーンショットになります。

今回は、二つのサンプルを用意したのですが、上の方がCSSの三角関数をCSSのanimationで動かしているもの。下の方がCSSの三角関数をJavaScriptで動かしているものです。

本当は、両方とも楕円の動きをさせたかったのですが、CSSの方は菱形の動きになっています。その理由について、確認したいと思います。

コードの確認

使用しているHTMLについて、こちらが、CSSアニメーション版のもの(抜粋)になります。

<style>
    .circle {
        width: 600px;
        height: 300px;
        position: relative;
        background-color: aliceblue;
        margin: 30px auto;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .css-circle {
        width: 30px;
        height: 30px;
        border-radius: 9999px;
        background-color: rgb(147, 147, 12);
        animation: loop 5s linear infinite;
    }

    @keyframes loop {
        0% {
            transform: translate(calc(cos(0deg) * 260px), calc(sin(0deg) * 120px * -1));
        }

        25% {
            transform: translate(calc(cos(90deg) * 260px), calc(sin(90deg) * 120px * -1));
        }

        50% {
            transform: translate(calc(cos(180deg) * 260px), calc(sin(180deg) * 120px * -1));
        }

        75% {
            transform: translate(calc(cos(270deg) * 260px), calc(sin(270deg) * 120px * -1));
        }

        100% {
            transform: translate(calc(cos(360deg) * 260px), calc(sin(360deg) * 120px * -1));
        }
    }
</style>
<div class="circle">
    <div class="css-circle"></div>
</div>

そして、こちらがJavaScriptで動かしているコード(抜粋)になります。

<style>
    .circle {
        width: 600px;
        height: 300px;
        position: relative;
        background-color: aliceblue;
        margin: 30px auto;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .js-circle {
        width: 30px;
        height: 30px;
        border-radius: 9999px;
        background-color: rgb(208, 72, 174);
    }
</style>
<script>
    window.onload = function () {
        let circle = document.querySelector('.js-circle');
        let degree = 0;

        let circleAnimation = function () {
            circle.style.transform = "translate( calc( cos(" + degree + "deg) * 260px ) ,
             calc( sin(" +
                degree +
                "deg) * 120px * -1) )";
            if (degree > 358) {
                degree = 0;
            } else {
                degree = degree + 3;
            }
        }
        setInterval(circleAnimation, 30);
    }
</script>
<div class="circle">
    <div class="js-circle"></div>
</div>

どうやって動かしているか

CSS版

次に、どのようにして動かしているかという部分について、CSS版の方から確認していきます。

まず、円の親となるタグを設定し、円をflexを使って中心部に配置します。そして、positionを併用して、表示位置を変更しているのですが、その値を決める際に、三角関数を用いています。

あとは、CSSアニメーションを使って、三角関数の角度部分を増やしています。

JavaScript版

一方、JavaScript版はというと、基本の配置はCSS版と同じなのですが、positionで位置を変更する際に、角度をJavaScriptを用いて加算しています。三角関数の角度が、都度上書きされています。

あと、繰り返し処理を行う際に、setIntervalを用いて繰り返し処理をしています。JavaScriptの繰り返しには、「requestAnimationFrame()」もありますが、繰り返しのスピードを調整することができません。ですので、今回のサンプルでは、setIntervalを用いてます。

CSS版は、三角関数を計算してから代入している?

そして、CSS版が想定通り動かなかった理由ですが、おそらく三角関数を設定した際に、CSSが『あらかじめ数値を計算してしまう=角度を変化させるのではなく計算した数値を変化させている』ためだと思います。

CSSの三角関数の今後

今回、CSSの三角関数を使ったサンプルを作ってみました。CSSで三角関数が使えるのは、確かにありがたいのですが、簡単にアニメーションを実装できるという訳ではないので、今の時点では使い所を見つけるのが難しいです。

もし、『CSSの三角関数ならでは』というのが登場すれば別ですが、そうでなければ、あまり登場の出番はなさそうな気がします。

関連記事