HTML・CSS・JSで円の中心角を自由に定義する

# 完成デモ
<p class="codepen" data-height="400" data-default-tab="html,result" data-slug-hash="jORjOOe"</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# コード解説

実際に使っているのは，一つの円と六つの三角形になります．

## HTML

```index.html
<div id="selects">
    <div>
      <label for="angle">中心角（度）：</label>
      <input type="number" id="angle" name="angle" value="0" min="0" max="360" oninput="changeAngle(this.value); changeAngle(this.value);">
    </div>
    <div>
      <label for="radius">半径：</label>
      <input type="range" id="radius" name="radius" min="50" max="500" value="200" oninput="changeRadius(this.value);">
    </div>    
  </div>
  <div class="circle2">  <!-- 円の枠 -->
    <div class="triangle1" id="triangle1"></div>
    <div class="triangle2" id="triangle2"></div>
    <div class="triangle3" id="triangle3"></div>
    <div class="triangle4" id="triangle4"></div>
    <div class="triangle5" id="triangle5"></div>
    <div class="triangle6" id="triangle6"></div>
  </div>
```

## CSS
1. .circle2 に`border-radius:50%;`を使い円形にする．
1. .circle2 に`overflow: hidden;`を使用して子要素の中で.circle2 の外側のものを表示しないようにする．
1. displayのgrid layoutを使用することによってtriangle1~6の位置をずれないように固定する．
glid layoutについては<a href="https://qiita.com/zono0013/items/783d561391ac26434b39">こちら</a>をどうぞ
1. `border-right: calc(var(--radius) * 1.25 * sin(calc(var(--angle) * 1deg))) solid transparent;`，　`
    border-top: calc(var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg))) solid #f3c87d;`これらの二つでsinとcosを使った三角形の定義を行います．
1. `transform-origin: left bottom;`回転の中心を要素の左下に合わせる 
1. `transform: translate(calc(var(--radius) / 2), calc(var(--radius) / 2 - var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg))));`5．で定義した要素の回転中心と円の中心が一致するように場所を合わせてあげる．
1. triangle2~6の`6.`はrotate(60*（idの数値-1）deg)を追加する．

```index.css
  :root {
    --radius: 200px; /* デフォルトの半径を定義 */
  }
  body {
    display: grid;
    place-items: center;
    height: calc(100vh - 16px);
    width: calc(100vw - 16px);
    grid-template-columns: repeat(5, 1fr);
    grid-template-rows: repeat(5, 1fr);
  }
  #selects {
    height: 100%;
    width: 100%;
    grid-column: 1/6;
    grid-row: 1/2;
    display: grid;
    align-items: center;
    justify-content: center;
    padding: 20px;
  }
  .circle2 {
    width: 200px;
    height: 200px;
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: 1fr;
    grid-column:2/5;
    grid-row:2/5;
    background-color: red; /* 円の背景色 */
    border-radius:50%; /* 円形にする */
    position: relative;
    overflow: hidden;
  }
  .triangle1{
    height: auto;
    width: auto;
    display: grid;
    grid-column: 1/2;
    grid-row: 1/2;
  }
  .triangle2{
    height: auto;
    width: auto;
    display: grid;
    grid-column: 1/2;
    grid-row: 1/2;
  }
  .triangle3{
    height: auto;
    width: auto;
    display: grid;
    grid-column: 1/2;
    grid-row: 1/2;
  }
  .triangle4{
    height: auto;
    width: auto;
    display: grid;
    grid-column: 1/2;
    grid-row: 1/2;
  }
  .triangle5{
    height: auto;
    width: auto;
    display: grid;
    grid-column: 1/2;
    grid-row: 1/2;
  }
  .triangle6{
    height: auto;
    width: auto;
    display: grid;
    grid-column: 1/2;
    grid-row: 1/2;
  }

  .triangle1::before {
    content: "";
    width: 0;
    height: 0;
    grid-column: 1/2;
    grid-row: 1/2;
    transform: translate(calc(var(--radius) / 2), calc(var(--radius) / 2 - var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg))));
    transform-origin: left bottom; 
    border-right: calc(var(--radius) * 1.25 * sin(calc(var(--angle) * 1deg))) solid transparent;
    border-top: calc(var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg))) solid #f3c87d;
  }
  .triangle2::before {
    content: "";
    width: 0;
    height: 0;
    grid-column: 1/2;
    grid-row: 1/2;
    transform-origin: left bottom; 
    transform: translate(calc(var(--radius) / 2), calc(var(--radius) / 2 - var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg)))) rotate(60deg);
    border-right: calc(var(--radius) * 1.25 * sin(calc(var(--angle) * 1deg))) solid transparent;
    border-top: calc(var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg))) solid #f3c87d;
  }
  .triangle3::before {
    content: "";
    width: 0;
    height: 0;
    grid-column: 1/2;
    grid-row: 1/2;
    transform-origin: left bottom; 
    transform: translate(calc(var(--radius) / 2), calc(var(--radius) / 2 - var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg)))) rotate(120deg);
    border-right: calc(var(--radius) * 1.25 * sin(calc(var(--angle) * 1deg))) solid transparent;
    border-top: calc(var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg))) solid #f3c87d;
  }
  .triangle4::before {
    content: "";
    width: 0;
    height: 0;
    grid-column: 1/2;
    grid-row: 1/2;
    transform-origin: left bottom;
    transform: translate(calc(var(--radius) / 2), calc(var(--radius) / 2 - var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg)))) rotate(180deg);
    border-right: calc(var(--radius) * 1.25 * sin(calc(var(--angle) * 1deg))) solid transparent;
    border-top: calc(var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg))) solid #f3c87d;
  }
  .triangle5::before {
    content: "";
    width: 0;
    height: 0;
    grid-column: 1/2;
    grid-row: 1/2;
    transform-origin: left bottom; 
    transform: translate(calc(var(--radius) / 2), calc(var(--radius) / 2 - var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg)))) rotate(240deg);
    border-right: calc(var(--radius) * 1.25 * sin(calc(var(--angle) * 1deg))) solid transparent;
    border-top: calc(var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg))) solid #f3c87d;
  }
  .triangle6::before {
    content: "";
    width: 0;
    height: 0;
    grid-column: 1/2;
    grid-row: 1/2;
    transform-origin: left bottom;
    transform: translate(calc(var(--radius) / 2), calc(var(--radius) / 2 - var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg)))) rotate(300deg);
    border-right: calc(var(--radius) * 1.25 * sin(calc(var(--angle) * 1deg))) solid transparent;
    border-top: calc(var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg))) solid #f3c87d;
  }
```
## JavaScript
changeAngle(angle)はHTMLの中心角度の欄の数値を引数にとって呼び出され，angleの値によってtriangle1~6のsin,cosに入る角度の値が変化します．

```index.js
function changeAngle(angle){
      document.getElementById('triangle1').style.setProperty('--angle', angle);
    }

    function changeRadius(radius) {
      // ケーキの半径を変更
      document.querySelector('.circle2').style.width = radius + "px";
      document.querySelector('.circle2').style.height = radius + "px";

      document.documentElement.style.setProperty('--radius', radius + "px");
    }

// 中心角のリセット
function reset_angle(){
  document.getElementById('triangle1').style.setProperty('--angle', 0);
  document.getElementById('triangle2').style.setProperty('--angle', 0);
  document.getElementById('triangle3').style.setProperty('--angle', 0);
  document.getElementById('triangle4').style.setProperty('--angle', 0);
  document.getElementById('triangle5').style.setProperty('--angle', 0);
  document.getElementById('triangle6').style.setProperty('--angle', 0);
  return true;
}


function changeAngle(angle){
  reset_angle();
  if(angle <= 60){
    document.getElementById('triangle1').style.setProperty('--angle', angle);
  }else if(angle <= 120){
    document.getElementById('triangle1').style.setProperty('--angle', 61);
    document.getElementById('triangle2').style.setProperty('--angle', angle - 60);
  }else if(angle <= 180){
    document.getElementById('triangle1').style.setProperty('--angle', 61);
    document.getElementById('triangle2').style.setProperty('--angle', 61);
    document.getElementById('triangle3').style.setProperty('--angle', angle - 120);
  }else if(angle <= 240){
    document.getElementById('triangle1').style.setProperty('--angle', 61);
    document.getElementById('triangle2').style.setProperty('--angle', 61);
    document.getElementById('triangle3').style.setProperty('--angle', 61);
    document.getElementById('triangle4').style.setProperty('--angle', angle - 180);
  }else if(angle <= 300){
    document.getElementById('triangle1').style.setProperty('--angle', 61);
    document.getElementById('triangle2').style.setProperty('--angle', 61);
    document.getElementById('triangle3').style.setProperty('--angle', 61);
    document.getElementById('triangle4').style.setProperty('--angle', 61);
    document.getElementById('triangle5').style.setProperty('--angle', angle - 240);
    
  }else{
    document.getElementById('triangle1').style.setProperty('--angle', 61);
    document.getElementById('triangle2').style.setProperty('--angle', 61);
    document.getElementById('triangle3').style.setProperty('--angle', 61);
    document.getElementById('triangle4').style.setProperty('--angle', 61);
    document.getElementById('triangle5').style.setProperty('--angle', 61);
    if(angle <= 360){
      document.getElementById('triangle6').style.setProperty('--angle', angle - 300);
    }else{
      document.getElementById('triangle6').style.setProperty('--angle', 61);
    }
  }

}
```

# 応用

https://qiita.com/zono0013/items/55e1ec7b350cc654a883

https://qiita.com/zono0013/items/a2fc6e3d45cd44953070