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

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

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

Как рисовать сектор? Учитывая степень X [0-360], я хочу нарисовать сектор X градусов. Могу ли я сделать это с помощью чистого 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 demo

$(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)');
});
+68
источник поделиться
13 ответов

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.

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

+152
источник

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

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

Для углов менее 180deg

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

  • Добавьте псевдоэлемент с верхними пограничными радиусами, такими же, как высота элемента и нижние радиусы как 0.

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

  • Трансформация: rotate(); псевдоэлемент, дополняющий требуемый угол,
    i.e., transform: rotate(180 - rqrd. angle);

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

enter image description here

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

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

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>

Благодарности. Я не хочу быть воровщиком, я использовал идеи, которые я ранее использовал здесь и .

+31
источник
другие ответы

Связанные вопросы


Похожие вопросы

Это помогает?

.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 квартала в круге, angular линейного градиента можно рассчитать в каждом квартале. И background-position определяет четверть:

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

Единственное, что остается, это то, откуда пришел использованный ограничитель цвета:

Рассмотрим 30-angularьную фигуру круга в первой четверти 1st quarter.

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

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

+18
источник

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

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

мои решения работают с сеткой из четырех полигонов, каждая из которых обеспечивает возможную начальную или конечную точку для значений 0-90 ° или. 0-100%, 90-180 ° соответственно. 0-100% и т.д., Разделяя центральную точку и, следовательно, есть два раза четыре сегмента. вы можете думать о механике как о стержне телескопа с несколькими сегментами, каждый из которых выполняет свою сегментированную работу от 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 Международный Лизенц.   

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

+9
источник
  • Вам нужно нарисовать круг
  • используйте 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>
+8
источник

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

#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>

DEMO: http://jsfiddle.net/F6qz9/

+7
источник

См. это, чтобы получить представление о том, как решить вашу проблему.

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

Демо

+5
источник

Все ответы здесь творческие. Удивительно, как люди решают одну и ту же проблему по-разному. Принятый ответ Сэмпсона действительно классный, но я не знаю, почему он решил нарисовать белую часть вместо зеленого, поэтому я решил поделиться модифицированной версией, которая на самом деле рисует зеленый. Я просто считаю это более простым, таким образом, я разделяю его, если другие считают это полезным.

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>
+5
источник

Так как я нуждался в этом динамически, вот маленький плагин 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 градусов.)

+4
источник

Вы можете использовать круг с пунктирной линией.

<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 круга.

+3
источник

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

Он использует очень специфическую ширину, высоту и ширину границы, а также прямоугольную обрезку, поэтому их необходимо тщательно обрабатывать, когда вам нужно изменить размеры. Самый важный момент, который следует обратить внимание на то, что если вы хотите изменить размер пирога, вам нужно обновить все значения em PROPORTIONATELY, что означает, что все они должны масштабироваться тот же фактор.

Обратите внимание, что полный полукруг должен быть добавлен, если пирог заполнен более чем на 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

+2
источник

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

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;
}
+1
источник

Просто чтобы добавить к ответам, вы можете сделать это, используя 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+')';

}

Как это работает, он проверяет процент и на основе предварительно рассчитанных точек останова генерирует многоangularьник, чтобы разрезать квадрат. Радиус границы превращает его в отрезок круга.

0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос