コムセント 技術情報

  1. TOP
  2. コムセント 技術情報
  3. cssで三角関数を分かりやすく手軽に使いたい!

cssで三角関数を分かりやすく手軽に使いたい!

中学生の時「好きな教科はなんですか?」と聞かれた際「数学と理科です」と答えるほどの生粋のリケジョがこの話題に食いつかないワケ無いのですが、cssの三角関数が使えるようになったとの記事を読んでいると「記述減らすために分かりずらい書き方してるな…」と思ったので今回は扱いやすい扇状配置のテンプレートを作っていこうと思います。

今回のサンプルはこのようなものを作ります。

テンプレートは記事の最後にあります↓

そもそもsin(), cos()が追加されて何ができるようになったのか

三角関数を用いれば、中心からの距離(半径)と角度を入力することで、辺の高さや長さを算出することができます。つまり【オブジェクトに対して円状や扇状に配置したい】が、簡単に叶うようになった訳です。

角度が変わっても使いまわせる扇状配置のテンプレートを考える

まず三角関数を使うにあたって入力が必要な項目は「中心からの距離」と「角度」、扇状配置に配置する場合は「角度」が「n番目の要素の角度」になり、更に「扇全体の角度」も必要になります。

例えば扇角度180度に中心から100px離してオブジェクトを上向きに5個配置したい場合
オブジェクト間の角度:180 ÷ 5 = 36
n番目の要素の角度:36 × n = 36n
意外と「n番目の要素の角度」を出すのは簡単ですね。

cssの三角関数において角度が0の時の位置が中心から右側、そして角度を増やすと下向きに時計回りで回ります。
この場合上向きに設置するので180度追加します。
n番目の要素の角度:180 + 36n

cssのtransform: transleatに落とし込む:
長さ (x軸):100px  × cos(180 + 36n) = 180 + 36n px
高さ (y軸):100px  × sin(180 + 36n) = 180 + 36n px

一通りの準備は出来たのでテンプレートになるよう成形して行きましょう。

カスタムプロパティを使用してそれぞれのアイテムに番号を振ります。必ず0から振るようにしてください。

例:

<li style="--index: 0"><a class="menuLink" href="#">HOME</a></li>
<li style="--index: 1"><a class="menuLink" href="#">SEARCH</a></li>
<li style="--index: 2"><a class="menuLink" href="#">NOTICE</a></li>
<li style="--index: 3"><a class="menuLink" href="#">DM</a></li>
<li style="--index: 4"><a class="menuLink" href="#">SETTING</a></li>

この数字を先ほどの数式の「n」に代入するとそれぞれの求めたい値が出るわけですね。

必要な入力項目をまとめていきましょう。

/*アイテムを配置する全体の角度*/
--useangle: 180deg;
/*中心からの距離*/
--range: 100px;
/*アイテムの個数-1*/
--quantity: 4;
/*一番最初のアイテムの角度*/
--startangle: 180deg;

そしてテンプレートになります。

--angle: calc(var(--startangle) + calc(var(--useangle) / var(--quantity) * var(--index)));
--x: calc(cos(var(--angle)) * var(--range));
--y: calc(sin(var(--angle)) * var(--range));
translate: calc(var(--x) - 50%) calc(var(--y) - 50%);

これに加えて見て目を綺麗にする記述も加えていきます。
下記の一部は参考例なので都度変更してください。

/*中央に配置する記述*/
position: absolute;
top: 50%;
left: 50%;
/*見た目の記述*/
display: flex;
align-items: center;
justify-content: center;
border-radius: 40px;
width: 60px;
height: 60px;
background-color: #77D8E1;

liタグに関する記述は一通りできました!
周りの装飾を含めた全体の記述が下記になります。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>メニューサンプル</title>
  <style>
    :root {
      /*アイテムを配置する全体の角度*/
      --useangle: 180deg;
      /*中心からの距離*/
      --range: 100px;
      /*アイテムの個数-1*/
      --quantity: 4;
      /*一番最初のアイテムの角度*/
      --startangle: 180deg;
    }
    ul {
      position: absolute;
      margin: 0;
      padding: 0;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      list-style: none;
    }

    ul li {
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 40px;
      width: 60px;
      height: 60px;
      background-color: #77D8E1;
      position: absolute;
      top: 50%;
      left: 50%;
      /*テンプレート部分*/
      --angle: calc(var(--startangle) + calc(var(--useangle) / var(--quantity) * var(--index)));
      --x: calc(cos(var(--angle)) * var(--range));
      --y: calc(sin(var(--angle)) * var(--range));
      translate: calc(var(--x) - 50%) calc(var(--y) - 50%);
    }
    a {
      text-decoration: none;
      color: #2c2c46;
    }
  </style>
</head>

<body>
  <div>
    <ul>
      <li style="--index: 0"><a class="menuLink" href="#">HOME</a></li>
      <li style="--index: 1"><a class="menuLink" href="#">SEARCH</a></li>
      <li style="--index: 2"><a class="menuLink" href="#">NOTICE</a></li>
      <li style="--index: 3"><a class="menuLink" href="#">DM</a></li>
      <li style="--index: 4"><a class="menuLink" href="#">SETTING</a></li>
    </ul>
  </div>
</body>

</html>
上記のサンプルはこのように表示されます。

テンプレート

:root {
      /*アイテムを配置する全体の角度*/
      --useangle: 180deg;
      /*中心からの距離*/
      --range: 100px;
      /*アイテムの個数-1*/
      --quantity: 4;
      /*一番最初のアイテムの角度*/
      --startangle: 180deg;
    }
li {
     position: absolute;
     top: 50%;
     left: 50%;
     /*テンプレート部分*/
     --angle: calc(var(--startangle) + calc(var(--useangle) / var(--quantity) * var(--index)));
     --x: calc(cos(var(--angle)) * var(--range));
     --y: calc(sin(var(--angle)) * var(--range));
     translate: calc(var(--x) - 50%) calc(var(--y) - 50%);
   }

少し記述は増えますが、扱いやすいものになったと思います!
皆様も良き数学ライフを!(違)

おすすめ記事