どうしてもCSSで単振動のアニメーションを作らないといけなくなったときに読む記事

## この記事の概要

色々な都合があって、CSSだけで単振動のアニメーションを実装しないといけなくなるタイミング、ありますよね。
そんなときにこの記事を読んでもらえれば解決します。

:::note alert
ネタです！
:::

## 純粋なCSS

ひとまず完成形です。
（セットアップが楽なのでViteを使いましたが、Viteである意味はありません。）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/1ed61c7e-c245-6aa4-43cd-a7cda1da4eb2.gif" alt="" width="480">

以下で、近似した値を計算して、どうにか実装できました。
……こんなコード、絶対に手動で書きたくないですよね？

```css
.element {
  animation: simple-harmonic-motion 2000ms linear infinite;
}

@keyframes simple-harmonic-motion {
  0% {
    transform: translateY(calc(100px * 0));
  }
  5% {
    transform: translateY(calc(100px * 0.30902));
  }
  10% {
    transform: translateY(calc(100px * 0.58779));
  }
  15% {
    transform: translateY(calc(100px * 0.80902));
  }
  20% {
    transform: translateY(calc(100px * 0.95106));
  }
  25% {
    transform: translateY(calc(100px * 1));
  }
  30% {
    transform: translateY(calc(100px * 0.95106));
  }
  35% {
    transform: translateY(calc(100px * 0.80902));
  }
  40% {
    transform: translateY(calc(100px * 0.58779));
  }
  45% {
    transform: translateY(calc(100px * 0.30902));
  }
  50% {
    transform: translateY(calc(100px * 0));
  }
  55% {
    transform: translateY(calc(100px * -0.30902));
  }
  60% {
    transform: translateY(calc(100px * -0.58779));
  }
  65% {
    transform: translateY(calc(100px * -0.80902));
  }
  70% {
    transform: translateY(calc(100px * -0.95106));
  }
  75% {
    transform: translateY(calc(100px * -1));
  }
    80% {
    transform: translateY(calc(100px * -0.95106));
  }
  85% {
    transform: translateY(calc(100px * -0.80902));
  }
  90% {
    transform: translateY(calc(100px * -0.58779));
  }
  95% {
    transform: translateY(calc(100px * -0.30902));
  }
  100% {
    transform: translateY(calc(100px * 0));
  }
}
```

## PostCSSを使う

PostCSSはJavaScript製ですが、CSSと名前に入っているのでCSSだと言い張って使ってみます。

まずは必要なパッケージをインストールします。

```shell
npm i postcss postcss-cli postcss-for postcss-preset-env
```

次に`postcss.config.js`を作成します。

```javascript:postcss.config.js
module.exports = {
  plugins: {
    "postcss-preset-env": {
      features: {
        "trigonometric-functions": true,
      },
    },
    "postcss-for": true
  },
};
```

`package.json`にコマンドを追加して、叩いておきます。

```diff_jsondoc:package.json
  {
    // 省略
    "scripts": {
+     "css:watch": "postcss style.css -o dist.css -w"
    },
  }
```

先ほど頑張って書いたCSSを以下のように編集します。
`postcss-for`によりループが指定できるようになり、`postcss-preset-env`の`trigonometric-functions`により三角関数が使えるようになります。

```css
.element {
  animation: simple-harmonic-motion 2000ms linear infinite;
}

@keyframes simple-harmonic-motion {
  @for $i from 0 to 100 by 5 {
    $i% {
      transform: translateY(calc(100px * sin($i * 3.6deg)));
    }
  }
}
```

これにより、出力された結果は冒頭に載せたCSSと同じになります。

## 最後に

「CSSで三角関数が使えるようになるかも、みたいなニュースをいつか見たなあ」と思って調べたら、まだまだ先は長そうでした。

https://developer.mozilla.org/en-US/docs/Web/CSS/sin#browser_compatibility

どうにか上手く実現できないかなあと考えていると、PostCSSを使えばできるかも……と浮かびました。
完全に実用性は無いコードなのですが、発想から実現までのプロセスとしては良かった気がして記事にしています。


---

最後まで読んでくださってありがとうございます！
Twitterでも情報を発信しているので、良かったらフォローお願いします！

https://twitter.com/xrxoxcxox

Devトークでのお話してくださる方も募集中です！

https://jobs.qiita.com/employers/qiita-inc/dev_talks/489