web-dev-qa-db-ja.com

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

$(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
Itay Gal

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>要素を追加します。この要素には、パスの描画場所と描画方法を決定する属性が1つあります。次の値で始まります。

M115,115

これにより、パスが前述の円の中心から始まるように指示されます。次に、この場所から次の場所まで線を引きます。

L115,5

これにより、円の中心から要素の上部まで垂直線が描画されます(上から5ピクセル)。この時点で、物事はもう少し複雑になりますが、それでも非常にわかりやすいです。

現在の場所(115,5)から円弧を描きます:

A110,110 1 0,1 190,35 z

これにより、円弧が作成され、円の半径(110)と一致する半径が与えられます。 2つの値はx半径とy半径を表し、円を扱っているため両方とも等しくなります。次の重要な数字のセットは最後の190,35です。これにより、アークが完了する場所がわかります。

残りの情報(1 0,1およびz)に関しては、これらはアーク自体の曲率、方向、および終端を制御します。オンラインSVGパスリファレンスを参照することで、それらについて詳しく知ることができます。

異なるサイズの「スライス」を実現するには、190,35を変更して、より大きなまたはより小さな座標セットを反映するだけです。 180度を超えてスパンする場合は、2つ目の円弧を作成する必要がある場合があります。

角度から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
Sampson

overflowおよびtransformプロパティを使用すると、複雑な計算を行う必要なく非常に可能です。

>回転変換

180度未満の角度の場合

  1. アスペクト比2:1およびoverflow: hidden;の要素を追加します

  2. 上部の境界半径が要素の高さと同じで、下部の半径が0の擬似要素を追加します。

  3. Put transform-Origin: 50% 100%;これは、中間要素から擬似要素を変換します。

  4. 変換:rotate();必要な角度の補足による擬似要素、
    i.e。、transform: rotate(180 - rqrd. angle);

仕組みを見る:

enter image description here

EG:
この方法を使用した40度のセクター: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 skewを使用して実行できます。
フィドル

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>

謝辞:自己窃盗になりたくありません。以前使用したアイデアを使用しました here および- ここ

31
The Pragmatick

これは役立ちますか?

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

Working Fiddle

実際、ここでは何らかのジオメトリ計算が必要です。しかし、簡単に説明しましょう:

円内の4つの四分の一を考慮すると、各四分の一で線形勾配の角度を計算できます。 background-positionは四半期を決定します:

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

残っている唯一のものは、使用されたcolor-stopがどこから来たかです:

第1四半期-angled円を考えてみましょう。

才能あるようにAna Tudorは彼女で説明しましたgreat article、正方形の幅の長さをaにすると、それから半分の対角線の長さはa*sqrt(2)/2になります。

勾配度をgとする場合、2つの勾配と対角の差を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-position100% 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>

詳細については、アナの記事を読むことをお勧めします。

17
Hashem Qolami

満足のいく答えがまったく見つからなかったので、最終的に必要なものを取得するために、clip-path関数と日曜日のcssを使用してひざまずきました。

開始角度と終了角度を選択すると、要素はそれだけでうまく描画されます。基本円を描くには、境界半径ソリューションだけが必要です。

私のソリューションは、4つのポリゴンのグリッドで動作し、それぞれが0〜90°の値の可能な開始点または終了点を提供します。 0-100%、90-180°それぞれ0-100%など、中心点を共有するため、4回のセグメントが2回あります。メカニックは、複数のセグメントを備えた望遠鏡のロッドと考えることができます。各セグメントは、メカニックのために0からNまでのセグメント化されたジョブを実行しますが、コード(0-90,90-180 ..) divを手動で回転(-45deg)する必要があったため、0°== 12 ''になりました。

ここに私がそれをやった方法を説明するかもしれない小さなスケッチがあります:

schema

私はオンラインのようなソリューションを見つけられなかったので、商用目的でこれを使用できないことに注意してください。したがって、それに何らかの価値が必要です。これを尊重してください。


cs von cを使用して円セグメントを描画します。 Schaefer ist lizenziert unter einerクリエイティブコモンズ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>
8
c. schaefer
  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>
7
Gavin

別の解決策があります。

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

7
Nolan

これを参照して、問題の解決方法を理解してください。

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

ここでの答えはすべて創造的です。人々がこれほど多くの方法で同じ問題を解決するのは驚くべきことです。サンプソンの受け入れられた答えは本当にクールですが、なぜ彼が緑の代わりに白い部分を描くことにしたのか分かりませんので、実際に緑を描く修正版を共有することを考えました。この方法でもう少しわかりやすいので、他の人にも役立つと思われる場合に備えて共有しています。

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

これは動的に必要だったので、ここに小さなjQueryプラグインがあります。例えば$('selector').pieChart(0.4, 'white' 'green')を呼び出して、40%の緑のセグメントを白い円に表示します。

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

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

これは、Racilの ここの例 に基づいています。 (注:180度を超えるセクターでは機能しないため、編集済みの回答でOPのプラグインを使用できませんでした。)

4
mahemoff

破線の円を使用できます。

<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>
  • 線を円の半径の2倍の太さにし、円の中心に到達するようにします。
  • stroke-dasharray値を操作して、表示するパイサイズの大きさを決定します。

ボーナス:パスの代わりに円を使用する利点は、円のサイズを変更するときに簡単にアニメーション化できることです。円のcssにtransition: stroke-dasharray .5s;のようなものを追加するだけです。

3
Karine Larouche

私のアプローチは少し異なり、SVGを使用せずに簡単にアニメーション化することができます。

非常に特定の幅、高さ、境界線幅、および長方形のクリッピングを利用するため、寸法を変更する必要がある場合はこれらを慎重に処理する必要があります。ここで注意すべき最も重要な点は、パイをresizeしたい場合は、allem比例的に-それらはすべて同じ係数でスケーリングする必要があることを意味します。

パイが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>

以下に、説明するフィドルを示します。これは、書面で説明するよりもはるかに簡単です。

Animated JSFiddle Demo

2
Alex

シンプル。以下のコードに従ってください:

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
Rajnish