Wie zeichne ich einen Kreissektor in CSS?

77

Das Zeichnen eines Kreises mit reinem CSS ist einfach.

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

Wie zeichne ich einen Sektor? Bei einem Grad X [0-360] möchte ich einen X-Grad-Sektor zeichnen. Kann ich das mit reinem CSS machen?

Zum Beispiel:

Geben Sie hier die Bildbeschreibung ein

Danke + Beispiel

Danke Jonathan, ich habe die erste Methode angewendet. Wenn es jemandem hilft, finden Sie hier ein Beispiel für eine JQuery-Funktion, die den Prozentsatz erhält und einen Sektor zeichnet. Der Sektor befindet sich hinter dem Prozentkreis und dieses Beispiel zeigt, wie ein Bogen um einen Kreis von einem Startgrad aus erreicht wird.

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)');
});
Itay Gal
quelle

Antworten:

167

CSS und mehrere Hintergrundverläufe

Anstatt zu versuchen, den grünen Teil zu zeichnen, können Sie stattdessen die weißen Teile zeichnen:

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

Demo: http://jsfiddle.net/jonathansampson/7PtEm/

Geben Sie hier die Bildbeschreibung ein

Skalierbare Vektorgrafiken

Wenn dies eine Option ist, können Sie mit SVG <circle>und <path>Elementen einen ähnlichen Effekt erzielen . Folgendes berücksichtigen:

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

Das obige ist ziemlich einfach. Wir haben ein Element, das einen Kreis und einen Pfad enthält. Der Mittelpunkt des Kreises liegt bei 115 x 115 (wodurch das SVG-Element 230 x 230 wird). Der Kreis hat einen Radius von 110, was eine Gesamtbreite von 220 ergibt (wobei ein Rand von 10 verbleibt).

Wir fügen dann ein <path>Element hinzu, was der komplizierteste Teil dieses Beispiels ist. Dieses Element verfügt über ein Attribut, das bestimmt, wo und wie der Pfad gezeichnet wird. Es beginnt mit folgendem Wert:

M115,115

Dies weist den Pfad an, in der Mitte des oben genannten Kreises zu beginnen. Als nächstes ziehen wir eine Linie von diesem Ort zum nächsten Ort:

L115,5

Dadurch wird eine vertikale Linie vom Mittelpunkt des Kreises bis zur Oberseite des Elements gezogen (also fünf Pixel von der Oberseite). An diesem Punkt werden die Dinge etwas komplizierter, aber immer noch sehr verständlich.

Wir zeichnen jetzt einen Bogen von unserem gegenwärtigen Standort (115,5):

A110,110 1 0,1 190,35 z

Dies erzeugt unseren Bogen und gibt ihm einen Radius, der dem unseres Kreises (110) entspricht. Die beiden Werte stellen den x-Radius und den y-Radius dar und beide sind gleich, da es sich um einen Kreis handelt. Der nächste Satz wichtiger Zahlen ist der letzte 190,35. Dies teilt dem Bogen mit, wo er abgeschlossen werden soll.

Was den Rest der Informationen ( 1 0,1und z) betrifft, steuern diese die Krümmung, Richtung und das Ende des Bogens selbst. Sie können mehr darüber erfahren, indem Sie eine Online-SVG-Pfadreferenz konsultieren.

Um ein "Slice" einer anderen Größe zu erzielen, ändern Sie einfach das 190,35, um einen größeren oder kleineren Satz von Koordinaten wiederzugeben. Möglicherweise müssen Sie einen zweiten Bogen erstellen, wenn Sie mehr als 180 Grad überspannen möchten.

Wenn Sie die x- und y-Koordinaten aus einem Winkel bestimmen möchten, können Sie die folgenden Gleichungen verwenden:

x = cx + r * cos(a)
y = cy + r * sin(a)

Mit dem obigen Beispiel wäre ein Grad von 76:

x = 115 + 110 * cos(76)
y = 115 + 110 * sin(76)

Welches gibt uns 205.676,177.272.

Mit etwas Leichtigkeit können Sie Folgendes erstellen:

Demo: http://jsfiddle.net/jonathansampson/tYaVW/

Geben Sie hier die Bildbeschreibung ein

Sampson
quelle
2
Gute Antwort! Sehr ausführlich. Es ist zu beachten, dass Sie die SVG-Methode verwenden müssen, wenn Sie einen transparenten Hintergrund für den nicht verwendeten Teil des Kuchens haben möchten.
Neil Monroe
@NeilMonroe Das ist richtig, obwohl einige der Kuchenarrangements mit einer transparenten Farbe durchgeführt werden könnten, wodurch der Inhalt hinter dem Kuchen sichtbar wird.
Sampson
4
@ JonathanSampson, es hat mir sehr geholfen. Ich wünschte, ich könnte noch 10 weitere Stimmen abgeben. Danke :)
Hiral
2
Hier ist ein Tipp: Hinzufügen einer Transformation pie { transform: rotate(-90deg) }könnte die Berechnung erleichtern
Endless
1
Sollte das nicht cos (76 * pi / 180) und sin (76 * pi / 180) sein? 76 Grad ist das Folgende und Sie müssen auf der rechten Seite beginnen: 141.611408516,221.7325298904 dropbox.com/s/l9450gji5424hp9/…
Intellix
34

Dies ist mit overflowund transformEigenschaften sehr gut möglich, ohne dass komplexe Berechnungen durchgeführt werden müssen.

> Transformation drehen

Für Winkel unter 180 Grad

  1. Fügen Sie ein Element mit einem Seitenverhältnis von 2: 1 und hinzuoverflow: hidden;

  2. Fügen Sie ein Pseudoelement hinzu, dessen obere Randradien der Höhe des Elements und dessen untere Radien 0 entsprechen.

  3. Put transform-origin: 50% 100%;Dies transformiert das Pseudoelement von seinem mittleren Boden.

  4. Transformieren: drehen (); das Pseudoelement durch die Ergänzung des erforderlichen Winkels,
    dh .,transform: rotate(180 - rqrd. angle);

Sehen, wie es funktioniert :

Geben Sie hier die Bildbeschreibung ein

EG:
Ein 40-Grad-Sektor mit dieser Methode: Fiddle

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

> Schräglauftransformation

Sie können das Bild auch in den Sektor einfügen!

Dies kann mithilfe von skewTransformationen auf Parent und -ve Skew auf Pseudoelement:
Fiddle erfolgen

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

Sehen Sie, wie das funktioniert:

Geben Sie hier die Bildbeschreibung ein


Danksagung : Ich möchte kein Selbstdiebstahler sein, ich habe die Ideen verwendet, die ich zuvor hier und hier verwendet hatte .

Der Pragmatick
quelle
19

Hilft das?

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

Geige arbeiten

Tatsächlich ist hier eine Geometrieberechnung erforderlich. Aber lassen Sie mich das kurz erklären:

Unter Berücksichtigung der 4 Viertel im Kreis kann der Winkel des linearen Gradienten in jedem Viertel berechnet werden. Und das background-positionbestimmt das Quartal:

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

Es bleibt nur noch, woher der verwendete Farbstopp stammt:

Betrachten Sie ein 30-Winkel- Stück Kreis im 1. Quartal .

Wie die talentierte Ana Tudor in ihrem großartigen Artikel erklärt hat: Wenn wir die Länge der Breite des Quadrats annehmen a, dann wird die Länge der halben Diagonale sein a*sqrt(2)/2.

Wenn wir den Gradientengrad als gDifferenz zwischen zwei Gradienten- und Diagonalwinkeln betrachten, kann ddie Länge von color-stopberechnet werden durch:

a*sin(g) / (a*sqrt(2)/2 * cos(d))
= sin(g) / (sqrt(2)  /2 * cos(d)) 

In diesem Fall haben wir also sin(30deg) / (sqrt(2)*cos((45-30)deg)) = 0.3660, und der% -Wert für den Farbstopp ist36.60%

Da unsere Form im 1. Quartal ist, background-positionist das 100% 0.

und der lineare Gradient wäre wie folgt :

linear-gradient(-30deg, orange 36.60%, transparent 36.60%) 100% 0;

Ich empfehle, den Artikel von Ana für weitere Details zu lesen.

Hashem Qolami
quelle
Ich bin mir nicht sicher, ob ich die Lösung verstehe. Was ist, wenn ich die Grade auf 236 einstellen möchte? Wenn ich den 36-Grad-Wert auf 236-Grad ändere, wird nicht das erwartete Ergebnis angezeigt.
Itay Gal
@ItayGal Vielleicht möchten Sie diesen brillanten Beitrag von Ana Tudor lesen .
Lars Beck
Wenn ich versuche, diese Gleichung für 120 Grad zu verwenden, funktioniert sie nicht. Können Sie mir bitte eine Beispielgleichung für 120 Grad geben
grvpanchal
9

Da ich überhaupt keine zufriedenstellende Antwort fand, musste ich auf die Knie gehen und die Clip-Path-Funktion und einen ganzen Sonntag CSS verwenden, um endlich das zu bekommen, was ich wollte.

Sie können einen Start- und einen Endwinkel auswählen, und dann zeichnet das Element genau das, sonst nichts. Sie benötigen nur die Randradiuslösung zum Zeichnen des Grundkreises.

Meine Lösungen arbeiten mit einem Raster aus vier Polygonen, die jeweils einen möglichen Start- oder Endpunkt für die Werte 0-90 ° bzw. 0-100%, 90-180 ° resp. 0-100% und so weiter, teilen sich den Mittelpunkt und daher gibt es zwei mal 4 Segmente. Sie können sich die Mechanik als Teleskopstange mit mehreren Segmenten vorstellen, von denen jedes aufgrund der Mechanik seine segmentierte Aufgabe von 0 bis N erfüllt, während der Code (0-90,90-180 ..), d. h musste das div manuell drehen (-45deg), so dass 0 ° == 12 ''.

Hier ist eine kleine Skizze, die veranschaulichen kann, wie ich es gemacht habe:

Schema

Bitte beachten Sie, dass Sie dies nicht für kommerzielle Zwecke verwenden können, da ich online keine solche Lösung gefunden habe. Daher muss es einen gewissen Wert geben. Bitte respektiere dies.


Zeichnen von Kreissegmenten mit css von c. schaefer ist lizenziert unter einer Creative Commons Namensnennung - Nicht geführtl - Keine Rechteungen 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>

c. schaefer
quelle
9
  1. Sie müssen einen Kreis zeichnen
  2. Verwenden clip-pathSie diese Option, um einen Sektor zu schneiden (Sie müssen etwas rechnen).

Hier können Sie clip-path herumspielen

Hier ist eine Demo:

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

Gavin
quelle
Es funktioniert Chrome, aber es funktioniert nicht Firefox-Browser und andere Browser. Geben Sie eine Idee
Karthi
@karthi Firefox unterstützt clip-pathnur den in SVG definierten Pfad. Sie können SVG also als Problemumgehung verwenden. Während für IE kenne ich keine bessere Lösung als Bilder.
Gavin
Kannst
@karthi Ich habe kein Beispiel zur Hand, aber Sie können stackoverflow.com/questions/33816793/… für ein Beispiel überprüfen
Gavin
7

Ich habe eine andere Lösung.

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

Nolan
quelle
Dies wird für einen halben Kuchen funktionieren. Wenn Sie den gesamten Bereich benötigen, können Sie diese Technik anwenden und dem Kreiselement eine Spanne für zwei weitere Pseudoelementstile hinzufügen.
Neil Monroe
5

Sehen Sie sich dies an, um eine Vorstellung davon zu bekommen, wie Sie Ihr Problem lösen können.

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

Demo

MichaB
quelle
1
Schöne Trickknospe! Aber eines - Sie können keine transparenten Sektoren mit einem Winkel <45 erstellen;) Sie können sicherlich versteckte Sektoren erstellen.
Der Pragmatick
5

Alle Antworten hier sind kreativ. Es ist erstaunlich, wie Menschen das gleiche Problem auf so viele Arten lösen. Die akzeptierte Antwort von Sampson ist wirklich cool, aber ich weiß nicht, warum er beschlossen hat, den weißen Teil anstelle des grünen zu zeichnen. Deshalb habe ich mir überlegt, eine modifizierte Version zu teilen, die tatsächlich das Grün zeichnet. Ich finde es auf diese Weise nur ein bisschen einfacher, also teile ich es, falls andere es auch nützlich finden.

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>

Racil Hilan
quelle
4

Da ich dies dynamisch brauchte, ist hier ein kleines jQuery-Plugin. Rufen Sie z. B. $('selector').pieChart(0.4, 'white' 'green')an, um ein 40% grünes Segment auf einem weißen Kreis anzuzeigen.

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

Dies basiert auf Racils Beispiel hier . (Hinweis: Ich konnte das OP-Plugin in der bearbeiteten Antwort nicht verwenden, da es für Sektoren mit mehr als 180 Grad nicht funktioniert.)

Mahemoff
quelle
1
+1 für die Erwähnung meines Namens :). Nein, +1 für die Umwandlung in eine coole Funktion. Vielleicht solltest du daraus eine Bibliothek erstellen;).
Racil Hilan
3

Sie können einen Kreis mit einer gestrichelten Linie verwenden.

<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>
  • Machen Sie die Linie doppelt so dick wie der Radius des Kreises, so dass sie den Mittelpunkt des Kreises erreicht.
  • Spielen Sie mit dem stroke-dasharrayWert, um zu bestimmen, wie groß eine Kuchengröße sein soll.

Bonus: Der Vorteil der Verwendung eines Kreises anstelle eines Pfades besteht darin, dass Sie ihn leicht animieren können, wenn Sie die Kuchengröße ändern: transition: stroke-dasharray .5s;Fügen Sie einfach so etwas zum CSS des Kreises hinzu.

Karine Larouche
quelle
2

Ich habe einen etwas anderen Ansatz und einen, der ohne Verwendung von SVG einfach animiert werden kann.

Es werden sehr spezifische Breiten, Höhen und Randbreiten sowie rechteckige Ausschnitte verwendet, sodass diese beim Ändern der Abmessungen sorgfältig behandelt werden müssen. Der wichtigste Punkt hier beachten ist , dass , wenn Sie möchten die Größe der Torte, die Sie aktualisieren müssen alle die emWerte quoten - das heißt , sie alle um den gleichen Faktor skaliert werden müssen.

Beachten Sie, dass ein vollständiger Halbkreis hinzugefügt werden muss, wenn der Kuchen zu mehr als 50% gefüllt ist (> 180 Grad sind farbig). Dieser Teil sollte in JS dynamisch behandelt werden, wenn Sie ihn animieren.

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

Hier ist die Geige zu demonstrieren - was viel einfacher ist als schriftlich zu erklären:

Animierte JSFiddle-Demo

Alex
quelle
1
Animation war nicht Teil der Frage, sondern +1 für den Aufwand und die coole Lösung.
Racil Hilan
1

Einfach. Folgen Sie einfach dem Code unten:

Der HTML:

<div class="circle"></div>
<div class="pie"></div>

Das 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;
}
Rajnish
quelle
0

Um die Antworten zu ergänzen, können Sie dies auch über den Clip-Pfad tun. Fügen Sie den Randradius 50% und den Clip-Pfad mit einem Wert hinzu, der mit der folgenden Funktion generiert wurde.

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+')';

}}

So funktioniert es, es überprüft den Prozentsatz und generiert basierend auf einigen vorberechneten Haltepunkten ein Polygon zum Schneiden des Quadrats. Der Randradius verwandelt es in ein Kreissegment.

Dapu
quelle