LoginSignup
2
3

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

Last updated at Posted at 2024-05-05

完成デモ

コード解説

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

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%;を使い円形にする.
  2. .circle2 にoverflow: hidden;を使用して子要素の中で.circle2 の外側のものを表示しないようにする.
  3. displayのgrid layoutを使用することによってtriangle1~6の位置をずれないように固定する.
    glid layoutについてはこちらをどうぞ
  4. 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を使った三角形の定義を行います.
  5. transform-origin: left bottom;回転の中心を要素の左下に合わせる
  6. transform: translate(calc(var(--radius) / 2), calc(var(--radius) / 2 - var(--radius) * 1.25 * cos(calc(var(--angle) * 1deg))));5.で定義した要素の回転中心と円の中心が一致するように場所を合わせてあげる.
  7. 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);
    }
  }

}

応用

2
3
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3