Как нарисовать сектор круга в CSS?



ну, рисовать круг с чистым CSS легко.



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


как нарисовать сектор? Учитывая степень X [0-360] я хочу нарисовать сектор х градусов.
Могу ли я сделать это с помощью чистого CSS?



например:



enter image description here



Спасибо + Пример



спасибо, Джонатан, я использовал Первый способ. Если это кому-то помогает, вот пример функции 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)');
});
1402   11  

11 ответов:

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/

enter image description here

Масштабируемая Векторная Графика

если это опция, вы можете достичь аналогичного эффекта с помощью 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

это рисует вертикальную линию от центра окружности до верхней части элемента (ну, пять пикселей сверху). Именно в этот момент все становится немного сложнее, но все еще очень понятно.

теперь мы рисуем дугу из нашего текущего местоположения (115,5):

A110,110 1 0,1 190,35 z

это создает нашу дугу и дает ей радиус, соответствующий радиусу нашей окружности (110). Эти два значения представляют собой радиус x и радиус y, и оба равны, так как мы имеем дело с кругом. Следующий набор важных чисел-последний,190,35. Это говорит дуге, где завершить.

что касается остальной информации (1 0,1 и z) они управляют кривизной, направлением и концом самой дуги. Вы можете узнать больше о они, консультируясь с любой онлайн-ссылкой SVG path.

выполнить "срез" другого размера, просто измените 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/

enter image description here

это очень хорошо возможно с помощью overflow и transform свойства без необходимости делать сложные расчеты.

> поворот преобразование

для углов меньше 180 градусов

  1. добавить элемент соотношение сторон 2: 1 и overflow: hidden;

  2. добавить псевдо-элемент с радиусами верхней границы такой же, как высота элемента и нижних радиусов, как 0.

  3. поставить transform-origin: 50% 100%; это преобразует псевдо-элемент из его среднего дна.

  4. Transform: rotate (); псевдо-элемент путем дополнения требуемого угла,
    я.е.,transform: rotate(180 - rqrd. angle);

посмотреть, как это работает :

enter image description here

например :
Сектор 40deg, использующий этот метод : Скрипка

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 перекос на псевдоэлемент:
Скрипка

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

посмотрим, как это работает :

enter image description here

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

единственное, что остается, это где используется color-stop пришла с:

рассмотрим 30-угловая кусок круга в квартале.

как талантливый Ана Тудор объяснил в ней большая статья, если мы возьмем длину ширину площадь 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>

рекомендую читайте статью Ана для получения более подробной информации.

вы можете выбрать начальный и конечный угол, а затем элемент будет красиво рисовать просто это, ничего другого. вам понадобится только решение border-radius для рисования базовой окружности.

мои решения работают с сеткой из четырех полигонов, каждый из которых обеспечивает возможную начальную или конечную точку для значений 0-90° соответственно. 0-100%, 90-180° респ. 0-100% и так далее, разделяя центральную точку и, следовательно, есть два раза 4 сегментов. вы можете думать о механике как о телескопическом стержне с несколькими сегментами, каждый из которых выполняет свою сегментированную работу от 0 до N. из-за механики,сохраняя при этом некоторую ясность в коде (0-90, 90-180 ..), мне пришлось вручную повернуть (- 45deg) div, так что 0° == 12".

вот небольшой эскиз, который может показать, как я сделал это:

schema

обратите внимание, что вы не можете использовать это для каких-либо коммерческих целей, так как я не нашел такого решения в интернете, следовательно, должна быть какая-то ценность для него. пожалуйста, уважайте это.


рисование сегментов круга с помощью 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>

у меня есть другое решение.

#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);
}*/

демо

  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 {
    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 это пример. (Обратите внимание, что я не мог использовать плагин OP в отредактированном ответе, поскольку он не работает для секторов, охватывающих более 180 градусов.)

простой. Просто следуйте приведенному ниже коду:

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;
}

у меня немного другой подход, и тот, который можно легко анимировать без использования SVG.

Он использует очень специфическую ширину, высоту и ширину границ, а также прямоугольную обрезку, поэтому их нужно тщательно обрабатывать, когда вам нужно изменить размеры. Самый важный момент, чтобы отметить здесь, что если вы хотите изменение размера пирог, вам нужно обновить все the 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 Demo

Comments

    Ничего не найдено.