program tip

CSS에서 원 섹터를 그리는 방법은 무엇입니까?

radiobox 2020. 11. 6. 08:02
반응형

CSS에서 원 섹터를 그리는 방법은 무엇입니까?


음, 순수한 CSS로 원을 그리는 것은 쉽습니다.

.circle {
    width: 100px;
    height: 100px;
    border-radius: 100px;
    border: 3px solid black;
    background-color: green;
}

섹터는 어떻게 그리나요? X도 [0-360]이 주어지면 X도 섹터를 그리고 싶습니다. 순수한 CSS로 할 수 있습니까?

예를 들면 :

여기에 이미지 설명 입력

감사합니다 + 예

감사합니다 조나단, 나는 첫 번째 방법을 사용했습니다. 누군가에게 도움이된다면 백분율을 얻고 섹터를 그리는 JQuery 함수의 예가 있습니다. 섹터는 백분율 원 뒤에 있으며이 예제는 시작 각도에서 원 주위의 호를 얻는 방법을 보여줍니다.

$(function drawSector() {
  var activeBorder = $("#activeBorder");
  var prec = activeBorder.children().children().text();
  if (prec > 100)
    prec = 100;
  var deg = prec * 3.6;
  if (deg <= 180) {
    activeBorder.css('background-image', 'linear-gradient(' + (90 + deg) + 'deg, transparent 50%, #A2ECFB 50%),linear-gradient(90deg, #A2ECFB 50%, transparent 50%)');
  } else {
    activeBorder.css('background-image', 'linear-gradient(' + (deg - 90) + 'deg, transparent 50%, #39B4CC 50%),linear-gradient(90deg, #A2ECFB 50%, transparent 50%)');
  }

  var startDeg = $("#startDeg").attr("class");
  activeBorder.css('transform', 'rotate(' + startDeg + 'deg)');
  $("#circle").css('transform', 'rotate(' + (-startDeg) + 'deg)');
});
.container {
  width: 110px;
  height: 110px;
  margin: 100px auto;
}

.prec {
  top: 30px;
  position: relative;
  font-size: 30px;
}

.prec:after {
  content: '%';
}

.circle {
  position: relative;
  top: 5px;
  left: 5px;
  text-align: center;
  width: 100px;
  height: 100px;
  border-radius: 100%;
  background-color: #E6F4F7;
}

.active-border {
  position: relative;
  text-align: center;
  width: 110px;
  height: 110px;
  border-radius: 100%;
  background-color: #39B4CC;
  background-image: linear-gradient(91deg, transparent 50%, #A2ECFB 50%), linear-gradient(90deg, #A2ECFB 50%, transparent 50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>

<div class="container">
  <div id="activeBorder" class="active-border">
    <div id="circle" class="circle">
      <span class="prec">66</span>
      <span id="startDeg" class="90"></span>
    </div>
  </div>
</div>

JSFiddle 데모

$(function drawSector() {
    // Get degrees
    ...
    // Draw a sector
    if (deg <= 180) {
        activeBorder.css('background-image', 'linear-gradient(' + (90+deg) + 'deg, transparent 50%, #A2ECFB 50%), linear-gradient(90deg, #A2ECFB 50%, transparent 50%)');
    }
    else {
        activeBorder.css('background-image', 'linear-gradient(' + (deg-90) + 'deg, transparent 50%, #39B4CC 50%), linear-gradient(90deg, #A2ECFB 50%, transparent 50%)');
    }

    // Rotate to meet the start degree
    activeBorder.css('transform','rotate(' + startDeg + 'deg)');
});

CSS 및 다중 배경 그라디언트

초록색 부분을 그리는 대신 흰색 부분을 그릴 수 있습니다.

pie {
    border-radius: 50%;
    background-color: green;
}

.ten {
    background-image:
        /* 10% = 126deg = 90 + ( 360 * .1 ) */
        linear-gradient(126deg, transparent 50%, white 50%),
        linear-gradient(90deg, white 50%, transparent 50%);
}

pie {
  width: 5em;
  height: 5em;
  display: block;
  border-radius: 50%;
  background-color: green;
  border: 2px solid green;
  float: left;
  margin: 1em;
}

.ten {
  background-image: linear-gradient(126deg, transparent 50%, white 50%), linear-gradient(90deg, white 50%, transparent 50%);
}

.twentyfive {
  background-image: linear-gradient(180deg, transparent 50%, white 50%), linear-gradient(90deg, white 50%, transparent 50%);
}

.fifty {
  background-image: linear-gradient(90deg, white 50%, transparent 50%);
}


/* Slices greater than 50% require first gradient
   to be transparent -> green */

.seventyfive {
  background-image: linear-gradient(180deg, transparent 50%, green 50%), linear-gradient(90deg, white 50%, transparent 50%);
}

.onehundred {
  background-image: none;
}
<pie class="ten"></pie>
<pie class="twentyfive"></pie>
<pie class="fifty"></pie>
<pie class="seventyfive"></pie>
<pie class="onehundred"></pie>

데모 : http://jsfiddle.net/jonathansampson/7PtEm/

여기에 이미지 설명 입력

확장 가능한 벡터 그래픽

옵션 인 경우 SVG <circle><path>요소를 사용하여 유사한 효과를 얻을 수 있습니다 . 다음을 고려하세요:

<svg>
  <circle cx="115" cy="115" r="110"></circle>
  <path d="M115,115 L115,5 A110,110 1 0,1 190,35 z"></path>
</svg>

위의 내용은 매우 간단합니다. 원과 경로를 포함하는 요소가 있습니다. 원의 중심은 115x115입니다 (SVG 요소를 230x230으로 함). 원의 반지름은 110이며 너비는 총 220입니다 (테두리 10 개 남김).

그런 다음 <path>이 예제에서 가장 복잡한 부분 인 요소 를 추가합니다 . 이 요소에는 경로가 그려지는 위치와 방법을 결정하는 하나의 속성이 있습니다. 다음 값으로 시작합니다.

M115,115

이것은 앞서 언급 한 원의 중심에서 시작하도록 경로를 지시합니다. 다음으로이 위치에서 다음 위치로 선을 그립니다.

L115,5

이것은 원의 중심에서 요소의 상단까지 수직선을 그립니다 (우물, 상단에서 5 픽셀). 이 시점에서 상황이 조금 더 복잡해 지지만 여전히 매우 이해하기 쉽습니다.

이제 현재 위치 (115,5)에서 호를 그립니다.

A110,110 1 0,1 190,35 z

이것은 우리의 호를 만들고 우리의 원 (110)과 일치하는 반지름을줍니다. 두 값은 x- 반지름과 y- 반경을 나타내며, 원을 다루기 때문에 둘 다 같습니다. 다음 중요한 숫자 세트는 마지막 190,35. 이것은 완료 할 위치를 호에 알려줍니다.

나머지 정보 ( 1 0,1z)는 호 자체의 곡률, 방향 및 터미널을 제어합니다. 온라인 SVG 경로 참조를 참조하여 이에 대해 자세히 알아볼 수 있습니다.

다른 크기의 "슬라이스"를 만들려면 190,35더 크거나 작은 좌표 집합을 반영 하도록 변경하기 만하면 됩니다. 180도 이상 걸 으려면 두 번째 호를 만들어야 할 수도 있습니다.

각도에서 x 및 y 좌표를 결정하려면 다음 방정식을 사용할 수 있습니다.

x = cx + r * cos(a)
y = cy + r * sin(a)

위의 예에서 76 도는 다음과 같습니다.

x = 115 + 110 * cos(76)
y = 115 + 110 * sin(76)

우리에게 205.676,177.272.

쉽게 다음을 만들 수 있습니다.

circle {
  fill: #f1f1f1;
  stroke: green;
  stroke-width: 5;
}

path {
  fill: green;
}

svg.pie {
  width: 230px;
  height: 230px;
}
<svg class="pie">
  <circle cx="115" cy="115" r="110"></circle>
  <path d="M115,115 L115,5 A110,110 1 0,1 190,35 z"></path>
</svg>

<svg class="pie">
  <circle cx="115" cy="115" r="110"></circle>
  <path d="M115,115 L115,5 A110,110 1 0,1 225,115 z"></path>
</svg>

<svg class="pie">
  <circle cx="115" cy="115" r="110"></circle>
  <path d="M115,115 L115,5 A110,110 1 0,1 115,225 A110,110 1 0,1 35,190 z"></path>
</svg>

데모 : http://jsfiddle.net/jonathansampson/tYaVW/

여기에 이미지 설명 입력


복잡한 계산을 할 필요없이 overflowtransform속성을 사용하는 것이 매우 가능합니다 .

> 회전 변환

180도 미만의 각도

  1. 가로 세로 비율이 2 : 1 인 요소를 추가 하고overflow: hidden;

  2. 상단 테두리 반경이 요소 높이와 같고 하단 반경이 0 인 유사 요소를 추가합니다.

  3. Put transform-origin: 50% 100%;이것은 중간 하단에서 가상 요소를 변형합니다.

  4. 변환 : rotate (); 필요한 각도를 보충하여 의사 요소,
    .,transform: rotate(180 - rqrd. angle);

작동 방식보기 :

여기에 이미지 설명 입력

EG :
이 방법을 사용하는 40deg 섹터 : Fiddle

div {
  ...
  overflow: hidden;
  ...
}
div:before {
  ...
  border-radius: 100px 100px 0 0;
  transform-origin: 50% 100%;
  transform: rotate(140deg);
  ...
}

div {
  height: 100px;
  width: 200px;
  overflow: hidden;
  position: relative;
}
div:before {
  height: inherit;
  width: inherit;
  position: absolute;
  content: "";
  border-radius: 100px 100px 0 0;
  background-color: crimson;
  -webkit-transform-origin: 50% 100%;
  -moz-transform-origin: 50% 100%;
  -ms-transform-origin: 50% 100%;
  transform-origin: 50% 100%;
  -webkit-transform: rotate(140deg);
  -moz-transform: rotate(140deg);
  -ms-transform: rotate(140deg);
  transform: rotate(140deg);
}
<div></div>

> 기울이기 변환

섹터 안에 이미지를 넣을 수도 있습니다!

이것은 skew부모에 대한 변환 및 의사 요소에 대한 -ve 왜곡을 사용하여 수행 할 수 있습니다 .
Fiddle

div {
    ...
    overflow: hidden;
    transform-origin: 0% 100%;
    transform: skew(-50deg);  /*Complement of rqrd angle*/
    ...
}
div:before {
    ...
    transform-origin: 0% 100%;
    transform: skew(50deg);
    ...
}

이것이 어떻게 작동하는지보기 :

여기에 이미지 설명 입력

div {
  height: 200px;
  width: 200px;
  overflow: hidden;
  -webkit-transform-origin: 0% 100%;
  -moz-transform-origin: 0% 100%;
  -ms-transform-origin: 0% 100%;
  transform-origin: 0% 100%;
  -webkit-transform: skew(-50deg);
  -moz-transform: skew(-50deg);
  -ms-transform: skew(-50deg);
  transform: skew(-50deg); /*Complement of rqrd angle or (90 - angle)*/
  position: relative;
}
div:before {
  height: inherit;
  width: inherit;
  position: absolute;
  content: "";
  border-radius: 0 200px 0 0;
  background: url('http://www.placekitten.com/g/300/200/');
  -webkit-transform-origin: 0% 100%;
  -moz-transform-origin: 0% 100%;
  -ms-transform-origin: 0% 100%;
  transform-origin: 0% 100%;
  -webkit-transform: skew(50deg);
  -moz-transform: skew(50deg);
  -ms-transform: skew(50deg);
  transform: skew(50deg);
}
<div></div>


감사의 말 : 나는 자기 도둑이되고 싶지 않습니다 . 이전에 여기여기에서 사용했던 아이디어를 사용했습니다 .


도움이 되나요?

.circle {
  width: 16em;
  height: 16em;
  border-radius: 50%;
  background: linear-gradient(36deg, #272b66 42.34%, transparent 42.34%) 0 0;
  background-repeat: no-repeat;
  background-size: 50% 50%;
}
<div class="circle"></div>

작업 바이올린

실제로 여기에는 기하학 계산이 필요합니다. 그러나 간단히 설명하겠습니다.

원의 4 분기를 고려하면 각 분기마다 선형 기울기 각도를 계산할 수 있습니다. 그리고 background-position분기를 결정합니다.

Q I   =>  100% 0
Q II  =>  100% 100%
Q III =>  0    100%
Q IV  =>  0    0

남은 유일한 것은 사용 된 색상 중지 가 어디에서 왔는지입니다.

1 분기30 각 원을 생각해보십시오 .

재능있는 Ana Tudor 가 그녀의 위대한 기사 에서 설명했듯이 , 정사각형 너비의 길이를 취 a하면 절반 대각선 길이가 될 것 a*sqrt(2)/2입니다.

기울기 각도를 g두 기울기 각도와 대각선 각도의 차이 로 취하면 d길이는 다음과 color-stop같이 계산할 수 있습니다.

a*sin(g) / (a*sqrt(2)/2 * cos(d))
= sin(g) / (sqrt(2)  /2 * cos(d)) 

따라서이 경우에는가 sin(30deg) / (sqrt(2)*cos((45-30)deg)) = 0.3660있고 색상 중지에 대한 % 값은36.60%

우리의 모양은 1 분기에 때문에,이 background-position입니다 100% 0.

선형 그라디언트는 다음 과 같습니다 .

linear-gradient(-30deg, orange 36.60%, transparent 36.60%) 100% 0;

.circle {
  width: 16em;
  height: 16em;
  border-radius: 50%;
  background: linear-gradient(-30deg, orange 36.60%, transparent 36.60%) 100% 0;
  background-repeat: no-repeat;
  background-size: 50% 50%;
}
<div class="circle"></div>

자세한 내용은 Ana의 기사를 읽는 것이 좋습니다.


만족스러운 답을 전혀 찾지 못했기 때문에 마침내 내가 원하는 것을 얻기 위해 clip-path 기능과 CSS의 전체 일요일을 사용하여 무릎을 꿇어 야했습니다.

시작 각도와 끝 각도를 선택하면 요소가 그저 멋지게 그릴 것입니다. 기본 원을 그리는 데 테두리 반경 솔루션 만 필요합니다.

내 솔루션은 각각 0-90 ° resp 값에 대해 가능한 시작점 또는 끝점을 제공하는 4 개의 다각형 그리드로 작동합니다. 0-100 %, 90-180 ° resp. 0-100 % 등등, 중심점을 공유하므로 2 x 4 개의 퇴적물이 있습니다. 역학으로 인해 각각 0에서 N까지 분할 된 작업을 수행하는 여러 세그먼트가있는 망원경 막대로 역학을 생각할 수 있습니다. 0 ° == 12 ''가되도록 div를 수동으로 회전 (-45deg)해야했습니다.

여기 내가 어떻게했는지 보여주는 작은 스케치가 있습니다.

개요

온라인에서 그와 같은 해결책을 찾지 못했기 때문에 상업적인 목적으로 이것을 사용할 수 없으므로 가치가 있어야합니다. 이것을 존중하십시오.


css von c를 사용하여 원 세그먼트 그리기. schaefer ist lizenziert unter einer Creative Commons Namensnennung-Nicht kommerziell-Keine Bearbeitungen 4.0 International Lizenz.

            <script src="http://code.jquery.com/jquery-latest.js"></script>

<style type="text/css">
    .circle{
        position: absolute;
        top: 100px;

        width: 600px;
        height: 600px;
        border-radius: 50%;
        background-color: #FFFF00;
        opacity: .9;

        -webkit-transform: rotate(45deg);

}

<script type="text/javaScript">

    var obj;
    var start, end;
    function rangeStart(val) {
        obj =  $("body").find(".circle");
        start = val;
        setAngle(obj, start, end);
    }

    function rangeEnd(val) {
        obj =  $("body").find(".circle");
        end = val;
        setAngle(obj, start, end);
    }

    function applyMasking(obj) {
        obj.css("-webkit-clip-path", ptsToString());
    }

    // not working for degree start to be lower than end, hence, we set the interface to automatically adapt to that exception:
    /*
    function checkForRangeExceptions() {
        if(end < start) {
            $("body").find("input[name='rangeLower']").val($("body").find("input[name='rangeUpper']").val());
            $("body").find("input[name='rangeLower']").slider('refresh');
        }
    }
    */

    // setInterval(doit, 200);

    var angie = 0;
    function doit() {
        obj =  $("body").find(".circle");
        if(angie < 360)
            angie+=15;
        else angie = 0;
        setAngle(obj, 0, angie);
    }


    function ptsToString() {
        var str = "";
        str+="polygon(";
        for(var i=0; i < pts.length; i++) {
            str+=pts[i].x+"% ";
            if(i != pts.length-1)
                str+=pts[i].y+"% ,";
            else str+=pts[i].y+"%";
        }
        str+=")";
        return str;
    }

    /*
    gets passed an html element and sets its clip-path according to the passed angle,
    starting at 0°; note that from a clock perspective, we start at +45° and hence have 
    to add that value to passed angles later on:
    */
    var pts = 
    [
     {x: 50, y: 50}, {x: 0, y: 0}, {x: 0, y: 0},
     {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0},
     {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0}
    ];
    var lb, ub;
    var sa, ea;
    function setAngle(obj, start, end) {
        // if no start, set 0° as default:
        start = (start == undefined ? start = 0 : start);

        // find out upper and lower sector bounds: 
        lb = (angleToSector(start) * 2) - 1;
        ub = angleToSector(end) * 2;

        // find start end end angles:
        sa = mapAngleToPoint(start);
        ea = mapAngleToPoint(end); 

        // now set points except start point which is 0:
        for(var i=1; i < pts.length; i++) {

            // set all below lb to lb:
            if(i <= lb) { pts[i].x = sa.x; pts[i].y = sa.y; }

            // set all in between to max values:
            else if(i > lb && i < ub) {
                pts[i] = setMax(i);
            }

            // set all above ub to ub:
            else if(i >= ub) { pts[i].x = ea.x; pts[i].y = ea.y; }

        }

        // apply masking:
        applyMasking(obj);

    }

    // assuming that 100 need to map 90°:
    function angleToPerc(angle) {
        return angle * (100/90);
    }

    function lowerBound(angle) {
        return (mapAngleToSector(angle));
    }

    function uppperBound(angle){
        return (mapAngleToSector(angle));           
    }

    // sectors 1-4
    function angleToSector(angle) {
            if      (angle >= 0   && angle < 90)  return 1;
            else if (angle >= 90  && angle < 180) return 2;
            else if (angle >= 180 && angle < 270) return 3;
            else if (angle >= 270 && angle <= 360) return 4;
    }

    // this maps the passed angle to a coordinate value:
    var as;
    function mapAngleToPoint(angle) {
            var pt = {x: 0, y: 0};
            as = angleToSector(angle);
            if(as == 1)       {pt.x = angleToPerc(angle); pt.y = 0; }
            else if(as == 2)  {pt.x = 100; pt.y = angleToPerc(angle-90)}
            else if(as == 3)  {pt.x = 100-angleToPerc(angle-180); pt.y = 100; }
            else if(as == 4)  {pt.x = 0; pt.y = 100-angleToPerc(angle-270); }
            return pt;
    }

    // set a point to its max by index:
    function setMax(index) {
        var pt = {x: 0, y: 0};
        if      (index == 1 || index == 2) { pt.x = 100; pt.y = 0; }
        else if (index == 3 || index == 4) { pt.x = 100; pt.y = 100; }
        else if (index == 5 || index == 6) { pt.x = 0; pt.y = 100; }
        else if (index == 7 || index == 8) { pt.x = 0; pt.y = 0; }
        return pt;
    }

</script>

</head>

<body>

    <div class="circle">

    </div>

    <input type="range" name="rangeLower" value="0" min="0" max="360" onchange="rangeStart(this.value);">
    <input type="range" name="rangeUpper" value="66"min="0" max="360" onchange="rangeEnd(this.value);">


</body>


  1. 원을 그릴 필요
  2. clip-path섹터를 자르는 데 사용 (수학을해야 함)

여기서 놀 수 clip-path 있습니다.

다음은 데모입니다.

#skills {
  position: relative;
  width: 300px;
  height: 300px;
  margin: 30px auto;
}

.circle {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  position: absolute;
}

.animate {
  -webkit-transition: 0.2s cubic-bezier(.74,1.13,.83,1.2);
  -moz-transition: 0.2s cubic-bezier(.74,1.13,.83,1.2);
  -o-transition: 0.2s cubic-bezier(.74,1.13,.83,1.2);
  transition: 0.2s cubic-bezier(.74,1.13,.83,1.2);
}

.animate:hover {
  transform: scale(1.1);
  transform-origin: center center;
}

#part1 {
  background-color: #E64C65;
  -webkit-clip-path: polygon(50% 0, 50% 50%, 100% 41.2%, 100% 0);
  clip-path: polygon(50% 0, 50% 50%, 100% 41.2%, 100% 0);
}

#part2 {
  background-color: #11A8AB;
  -webkit-clip-path: polygon(50% 50%, 100% 41.2%, 100% 100%, 63.4% 100%);
  clip-path: polygon(50% 50%, 100% 41.2%, 100% 100%, 63.4% 100%);
}

#part3 {
  background-color: #4FC4F6;
  -webkit-clip-path: polygon(50% 50%, 36.6% 100%, 63.4% 100%);
  clip-path: polygon(50% 50%, 36.6% 100%, 63.4% 100%);
}

#part4 {
  background-color: #FFED0D;
  -webkit-clip-path: polygon(50% 50%, 0 100%, 36.6% 100%);
  clip-path: polygon(50% 50%, 0 100%, 36.6% 100%);
}

#part5 {
  background-color: #F46FDA;
  -webkit-clip-path: polygon(50% 50%, 0 36.6%, 0 100%);
  clip-path: polygon(50% 50%, 0 36.6%, 0 100%);
}

#part6 {
  background-color: #15BFCC;
  -webkit-clip-path: polygon(50% 50%, 0 36.6%, 0 0, 50% 0);
  clip-path: polygon(50% 50%, 0 36.6%, 0 0, 50% 0);
}
<div id="skills">
  <div id="part1" class="circle animate"></div>
  <div id="part2" class="circle animate"></div>
  <div id="part3" class="circle animate"></div>
  <div id="part4" class="circle animate"></div>
  <div id="part5" class="circle animate"></div>
  <div id="part6" class="circle animate"></div>
</div>


다른 해결책이 있습니다.

#pie {
  position: relative;
  width: 100px;
  height: 100px;
  background-color: #76dd76;
  border-radius: 50%;
  border: 1px solid #76dd76;
}

#pie:before,
#pie:after {
  position: absolute;
  content: "";
  display: block;
  width: 50%;
  height: 50%;
  -webkit-transform-origin: right bottom;
  -moz-transform-origin: right bottom;
  -ms-transform-origin: right bottom;
  transform-origin: right bottom;
  background-color: white;
  border-top-left-radius: 100%;
}

#pie:after {
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  transform: rotate(45deg);
}
<div id="pie"></div>

데모 : http://jsfiddle.net/F6qz9/


문제를 해결하는 방법에 대한 아이디어를 얻으려면 이것을 참조하십시오.

<div class="circle"></div>

.circle{
    width: 100px;
    height: 100px;
    background-color: green;
    border-radius: 100px;
    position: relative;
}

.circle:before,
.circle:after {
    border: 50px solid white;
    border-color: transparent transparent white white;
    border-radius: 100px;
    content: '';
    height: 0;
    position: absolute;
    top: 0;
    left: 0;
    width: 0;
    /* this is to have it white from 180 to 360 degrees on the left side */
    transform:rotate(45deg);
    -ms-transform:rotate(45deg); /* IE 9 */
    -webkit-transform:rotate(45deg); /* Safari and Chrome */
}

/* the green sector is now 180 minus 45 plus 0 degree */
.circle:after {
    transform:rotate(0deg);
    -ms-transform:rotate(0deg); /* IE 9 */
    -webkit-transform:rotate(0deg); /* Safari and Chrome */
}

/* the green sector is now 180 minus 45 plus -75 degree */
/*.circle:after {
    transform:rotate(-75deg);
    -ms-transform:rotate(-75deg);
    -webkit-transform:rotate(-75deg);
}*/

데모


여기에있는 모든 대답은 창의적입니다. 사람들이 여러 가지 방법으로 동일한 문제를 해결하는 방법은 놀랍습니다. Sampson이 받아 들인 대답은 정말 멋지지만 왜 그가 녹색 대신 흰색 부분을 그리기로 결정했는지 모르겠으므로 실제로 녹색을 그리는 수정 버전을 공유하려고 생각했습니다. 나는이 방법이 좀 더 간단하다는 것을 알기 때문에 다른 사람들도 유용하다고 생각할 경우를 대비하여 공유하고 있습니다.

pie {
    width: 5em;
    height: 5em;
    display: block;
    border-radius: 50%;
    border: 2px solid green;
    float: left;
    margin: 1em;
}

.ten {
    background-image:
      linear-gradient(-54deg, white 50%, transparent 50%),
      linear-gradient(-90deg, green 50%, transparent 50%);
}

.twentyfive {
    background-image:
      linear-gradient(0deg, white 50%, transparent 50%),
      linear-gradient(-90deg, green 50%, transparent 50%);
}

.fifty {
    background-image:
      linear-gradient(-90deg, green 50%, transparent 50%);
}

/* Slices greater than 50% require first gradient to be green -> transparent */

.seventyfive {
    background-image:
      linear-gradient(0deg, green 50%, transparent 50%),
      linear-gradient(-90deg, green 50%, transparent 50%);
}

.onehundred {
    background-color: green;
}
<pie class="ten"></pie>
<pie class="twentyfive"></pie>
<pie class="fifty"></pie>
<pie class="seventyfive"></pie>
<pie class="onehundred"></pie>


동적으로 필요했기 때문에 여기에 약간의 jQuery 플러그인이 있습니다. 예를 들어 $('selector').pieChart(0.4, 'white' 'green')흰색 원에 40 % 녹색 세그먼트를 표시하도록 호출 합니다.

// LIBRARY FUNCTION
$.fn.pieChart = function(proportion, bg, fg) {
  var angle, grads;
  angle = Math.round(360 * (proportion % 0.5) - 90);
  grads = [
    "linear-gradient(" + angle + "deg, " + (proportion < 0.5 ? bg : fg) + " 50%, transparent 50% )",
    "linear-gradient(-90deg, " + fg + " 50%, transparent 50%)"
  ];
  return $(this).css({
    'background-color': proportion==1 ? fg : bg,
    'background-image': grads.join(','),
    'border': '1px solid '+fg
  });
};

// DEMO
for (var i=0; i <= 10; i++) {
  $('<div class="pie" />').appendTo('body').pieChart(i/10, 'white', 'green');
}
.pie {
  display: inline-block;
  margin: 10px;
  border-radius: 50%;
  width: 100px;
  height: 100px;
}
<script src="https://code.jquery.com/jquery-3.0.0.js"></script>

이것은 여기 에있는 Racil의 예를 기반으로 합니다 . (참고로 180도 이상의 섹터에서는 작동하지 않으므로 편집 된 답변에서 OP의 플러그인을 사용할 수 없습니다.)


점선이있는 원을 사용할 수 있습니다.

<svg viewBox="-8 -8 16 16">
  <circle
    cx="0"
    cy="0"
    r="4"
    transform="rotate(270)"
    stroke-width="8"
    stroke-dasharray="4, 26"
    stroke="green"
    fill="none"
  />
</svg>
  • 선이 원의 중심에 도달하도록 원의 반지름보다 두 배 두껍게 만듭니다.
  • stroke-dasharray값을 가지고 플레이 하여보고 싶은 파이 크기의 크기를 결정하십시오.

보너스 : 경로 대신 원을 사용하는 장점은 원형 크기를 변경할 때 쉽게 애니메이션을 적용 할 수 있다는 것 transition: stroke-dasharray .5s;입니다. 원의 CSS에 비슷한 것을 추가하기 만하면 됩니다.


나는 약간 다른 접근 방식을 가지고 있으며 SVG를 사용하지 않고 쉽게 애니메이션 할 수있는 접근 방식을 가지고 있습니다.

직사각형 클리핑과 함께 매우 특정한 너비, 높이 및 테두리 너비를 사용하므로 치수를 변경해야 할 때 신중하게 처리해야합니다. 여기에서 주목해야 할 가장 중요한 점은 당신이하고 싶은 경우 것입니다 크기를 조정 파이를 업데이트 할 필요가 모든em 값을 비례 그들은 모두 같은 비율로 축소해야 의미 -.

파이가 50 % 이상 차면 반원을 추가해야합니다 (> 180도 색상). 이 부분은 애니메이션화하는 경우 JS에서 동적으로 처리되어야합니다.

<style>
.timer {
    position: relative;
    width: 4em;
    height: 4em;
    float: left;
    margin: 1px 30px 0 0;
}


.timer > #slice {
    position: absolute;
    width: 4em;
    height: 4em;
    clip: rect(0px, 4em, 4em, 2em);
}

.timer > #slice.gt50 {
    clip: rect(auto, auto, auto, auto);
}

.timer > #slice > .pie {
    border: 3.2em solid green;
    position: absolute;
    width: 3.8em;
    height: 3.8em;
    clip: rect(0em, 2em, 4em, 0em);
    -moz-border-radius: 2em;
    -webkit-border-radius: 2em;
    border-radius: 2em;
}

.timer > #slice > .pie.fill {
    -moz-transform: rotate(180deg) !important;
    -webkit-transform: rotate(180deg) !important;
    -o-transform: rotate(180deg) !important;
    transform: rotate(180deg) !important;
}

.timer.fill > #slice > .pie {
    border: transparent;
    background-color: green;
    width: 4em;
    height: 4em;
}
</style>    
<div class="timer fill">
</div>
<script>
const PIE_INTERVAL_TIME = 1000; // one second interval time
const PERCENT_INTERVAL = 1.67; // 100 / 60 seconds
const stopInterval = setInterval(pieInterval(), PIE_INTERVAL_TIME);

function pieInterval() {
    let percent = 0;
    return function() {
        percent += PERCENT_INTERVAL;
            const timer = $('.timer');
            const gt50 = percent > 50 ? 'gt50' : '';
            const pieFill = percent > 50 ? '<div class="pie fill"></div>' : '';
      let deg = (360/100) * percent;
      timer.html(
        `<div id="slice" class="${gt50}">
            <div class="pie"></div>
            ${pieFill}
        </div>`);

      if (percent >= 100) {
        deg = 360;
        clearInterval(stopInterval);
      }

      $('#slice').find('.pie').css({
        '-moz-transform':'rotate('+deg+'deg)',
        '-webkit-transform':'rotate('+deg+'deg)',
        '-o-transform':'rotate('+deg+'deg)',
        'transform':'rotate('+deg+'deg)'
       });
    };
}
</script>

다음은 시연 할 바이올린입니다. 이는 서면으로 설명하는 것보다 훨씬 간단합니다.

애니메이션 JSFiddle 데모


단순한. 아래 코드를 따르십시오.

HTML :

<div class="circle"></div>
<div class="pie"></div>

CSS :

.circle {
width: 11em;
height: 11em;
border-radius: 100%;
background: linear-gradient(360deg, #FFFFFF 100%, transparent 42.34%) 0 0;
background-repeat: no-repeat;
background-size: 100% 100%;
}

.pie {
width: 11em;
height: 11em;
border-radius: 100%;
background: linear-gradient(-80deg, #1BB90D 50%, transparent 40%) 0 0;
background-repeat: no-repeat;
background-size: 100% 55%;
position: relative;
margin-top: -176px;
border: 1px solid #808D1E;
}

답변에 추가하기 위해 clip-path를 사용하여이 작업을 수행 할 수도 있습니다. 다음 함수에서 생성 된 값으로 테두리 반경 50 % 및 클립 경로를 추가합니다.

function calc_arc(prc) {
let str = '50% 50%, 50% 0%';
if(prc >= 45)
    str += ',100% 0%';
else
    str += ','+ (50+(prc/.45)/2) + '% 0%';

if(prc >= 135) 
    str += ',100% 100%';
else {

    prc -= 45;
    if(prc > 0) {
    prc /= .9;
    str += ',100% '+prc + '%';
    }
}

if(prc >= 225) 
    str += ',0% 100%';
else {
    prc -= 135;
    if(prc>0) {
    prc /= .9;
    str += ','+(100-prc) + '% 100%';
    }
}
if(prc >= 315) 
    str += ',0% 0%';
else {
    prc -= 225;
    if(prc>0) {
    prc /= .9;
    str += ',0% '+(100-prc) + '%';}
}
if(prc >= 360)
    str += ',100% 0%';
else {
prc -= 315;
if(prc>0) {
    str += ','+(prc/.45)/2 + '% 0%';
    }
    }
return 'polygon('+str+')';

}

작동 방식은 백분율을 확인하고 미리 계산 된 중단 점을 기반으로 사각형을 자르는 다각형을 생성합니다. 테두리 반경은 원의 세그먼트로 바꿉니다.

참고 URL : https://stackoverflow.com/questions/21205652/how-to-draw-a-circle-sector-in-css

반응형