Як намалювати сектор кола в CSS?


77

Ну, намалювати коло чистим CSS легко.

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

Як намалювати сектор? Враховуючи ступінь X [0-360], я хочу намалювати сектор X градусів. Чи можу я це зробити за допомогою чистого CSS?

Наприклад:

введіть тут опис зображення

Спасибі + Приклад

Дякую Джонатане, я використав перший метод. Якщо це комусь допомагає, ось приклад функції JQuery, яка отримує відсоток і малює сектор. Сектор знаходиться позаду відсоткового кола, і цей приклад показує, як досягти дуги навколо кола з початкового ступеня.

Демонстрація 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)');
});

Відповіді:


168

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

Демо: 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

Це проводить вертикальну лінію від центру кола до верху елемента (ну, п'ять пікселів зверху). На цьому етапі все стає дещо складнішим, але все ще дуже зрозумілим.

Тепер ми малюємо дугу з нашого поточного місця (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.

З деякою легкістю ви можете створити наступне:

Демонстрація: http://jsfiddle.net/jonathansampson/tYaVW/

введіть тут опис зображення


2
Чудова відповідь! Дуже ретельно. Слід зазначити, що якщо ви хочете мати прозорий фон для невикористаної частини пирога, тоді ви повинні використовувати метод SVG.
Ніл Монро

@NeilMonroe Це правильно, хоча деякі композиції для пирогів можуть бути зроблені з прозорим кольором, таким чином розкриваючи вміст, що стоїть за пирогом.
Сампсон

4
@JonathanSampson це мені дуже допомогло .. хоч би я міг проголосувати ще 10 разів. Дякую :)
Хірал,

2
Ось порада: додайте трохи перетворень, pie { transform: rotate(-90deg) }щоб полегшити обчислення
нескінченні

1
Чи не повинно це бути cos (76 * pi / 180) та sin (76 * pi / 180)? 76 градусів - це наступне, і ви повинні починати з правого боку: 141.611408516, 221.7325298904 dropbox.com/s/l9450gji5424hp9/…
Intellix,

34

Це дуже можливо з використанням overflowі transformвластивостями без необхідності робити складні розрахунки.

> Повернути перетворення

Для кутів менше 180 градусів

  1. Додайте елемент із співвідношенням сторін 2: 1 таoverflow: hidden;

  2. Додайте псевдоелемент із радіусами верхньої межі, рівними висоті елемента, а радіусам низу - 0.

  3. Put transform-origin: 50% 100%;Це перетворює псевдоелемент із його середнього дна.

  4. Трансформувати: обертати (); псевдоелемент шляхом доповнення необхідного кута,
    тобто ,transform: rotate(180 - rqrd. angle);

Дивись, як це працює :

введіть тут опис зображення


Напр . : 40-градусний сектор із використанням цього методу: Скрипка

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

> Перетворення косих

Ви також можете помістити зображення всередину сектора!

Це можна зробити за допомогою 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);
    ...
}

Подивіться, як це працює:

введіть тут опис зображення


Подяка : Я не хочу бути самокрадом, я використовував ідеї, які раніше використовував тут і тут .


19

Це допомагає?

.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

Залишається лише те, звідки взявся використаний кольоровий стоп :

Розглянемо 30-кутовий шматочок кола в 1-й чверті .

Як пояснила талановита Ана Тудор у своїй чудовій статті , якщо взяти довжину ширини квадрата такою 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;

Рекомендую прочитати статтю Анни, щоб дізнатися більше.


Я не впевнений, що розумію рішення. Що робити, якщо я хочу встановити градуси на 236? Якщо я зміню значення 36deg на 236deg, це не дасть очікуваного результату.
Itay Gal

@ItayGal Можливо, ви захочете прочитати цей блискучий допис Ани Тудор.
Ларс Бек,

Коли я намагаюся використовувати це рівняння для 120 градусів, це не працює. Чи можете ви дати мені приклад рівняння для 120 градусів, будь ласка
grvpanchal

9

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

Ви можете вибрати кут початку і кінця, і тоді елемент буде красиво малювати саме це, нічого іншого. для малювання базового кола вам знадобиться просто рішення граничного радіусу.

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

ось невеликий нарис, який може проілюструвати, як я це зробив:

схеми

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


малювання сегментів кола за допомогою 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>


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


він працює chrome, але не працює браузер Firefox та інший браузер. дайте будь-яку ідею
karthi

@karthi Firefox підтримує clip-pathлише шлях, визначений у SVG. Тож ви можете використовувати SVG як обхідний шлях. Для IE я не знаю жодного кращого рішення, крім зображень.
Гевін

Чи можете ви на прикладі SVG .. я доно, як змінити ваш код у SVG
karthi

@karthi У мене зараз немає прикладу, але ви можете перевірити stackoverflow.com/questions/33816793/… для прикладу
Гевін

7

У мене є інше рішення.

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


Це вийде за половину пирога. Якщо вам потрібен повний діапазон, ви можете скористатися цією технікою та додати проміжок до елемента пирога ще для двох стилів псевдоелементів.
Ніл Монро

5

Перегляньте це, щоб отримати уявлення про те, як вирішити вашу проблему.

<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
Приємний трюк! Але одне - ви не можете створювати прозорі сектори з кутом <45;) Ви напевно можете створювати приховані сектори.
Прагматик

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>


4

Оскільки мені це потрібно було динамічно, ось невеликий плагін 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's тут . (Примітка. Я не зміг використовувати плагін OP у відредагованій відповіді, оскільки він не працює для секторів, що охоплюють більше 180 градусів.)


1
+1 за згадку мого імені :). Ні, +1 за перетворення його на круту функцію. Можливо, вам слід створити з цього бібліотеку;).
Рейсіл Хілан

3

Можна використовувати коло з пунктирною лінією.

<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 кола.


2

У мене дещо інший підхід, і той, який можна легко анімувати, не використовуючи 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


1
Анімація не була частиною питання, але +1 за зусилля та круте рішення.
Расіл Хілан,

1

Простий. Просто дотримуйтесь наведеного нижче коду:

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

0

Просто щоб додати відповіді, ви можете зробити це за допомогою кліп-шляху. Додайте радіус межі 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+')';

}

Як це працює, він перевіряє відсоток і на основі деяких заздалегідь розрахованих точок розриву генерує багатокутник для вирізання квадрата. Радіус кордону перетворює його на відрізок кола.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.