Подтвердить что ты не робот

Как нарисовать круг в 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>
4b9b3361

Ответ 1

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>

Ответ 2

Это очень хорошо, если использовать свойства 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>

Ответ 3

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

.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

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

Ответ 5

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

Ответ 6

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

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

Ответ 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);
}*/

Демо

Ответ 8

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

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>

Ответ 9

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

Ответ 10

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

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

Ответ 11

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

Ответ 12

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

Ответ 13

Просто чтобы добавить к ответам, вы можете сделать это, используя 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ьник, чтобы разрезать квадрат. Радиус границы превращает его в отрезок круга.