web-dev-qa-db-fra.com

Graphique en beignet simple CSS3

Ce que j'essaie de faire, c'est de créer un simple graphique en anneau. J'utilise actuellement CSS (3) uniquement mais je ne sais pas si c'est possible sans javascript.

Ce que j'ai jusqu'à présent: http://jsfiddle.net/aBP5Q/

HTML:

<div class="donut-container" style="background: #9C0;">
    <div class="donut-inner">
        <div class="donut-label">HTML</div>
    </div>
</div>

CSS:

.donut-container {
    width: 150px;
    height: 150px;
    float: left;
    -webkit-border-radius: 75px;
    -moz-border-radius: 75px;
    border-radius: 75px;
    margin-right: 20px;
}

.donut-inner {
    width: 134px;
    height: 134px;
    position: relative;
    top: 8px;
    left: 8px;
    background: #FFF;
    -webkit-border-radius: 65px;
    -moz-border-radius: 65px;
    border-radius: 65px;
}

.donut-label {
    line-height: 130px;
    text-align: center;
    font-size: 20px;
}

Je voudrais afficher les couleurs verte et bleue en tant que précentage. Donc, aucun vert n'est à 0% et le vert complet (360 degrés) est à 100%. Peut-être même avec une simple animation lorsque le graphique est chargé si possible.

Votre aide est très appréciée.

15
JasonK

SVG pour la victoire!

.item {
    position: relative;
    float: left;
}

.item h2 {
    text-align:center;
    position: absolute;
    line-height: 125px;
    width: 100%;
}

svg {
   -webkit-transform: rotate(-90deg);
    transform: rotate(-90deg);
}

.circle_animation {
  stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
  stroke-dashoffset: 440;
}

.html .circle_animation {
    -webkit-animation: html 1s ease-out forwards;
    animation: html 1s ease-out forwards;
}

.css .circle_animation {
    -webkit-animation: css 1s ease-out forwards;
    animation: css 1s ease-out forwards;
}

@-webkit-keyframes html {
  to {
    stroke-dashoffset: 80; /* 50% would be 220 (half the initial value specified above) */
  }
}

@keyframes html {
  to {
    stroke-dashoffset: 80;
  }
}

@-webkit-keyframes css {
  to {
    stroke-dashoffset: 160;
  }
}

@keyframes css {
  to {
    stroke-dashoffset: 160;
  }
}
<div class="item html">
    <h2>HTML</h2>
    <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
     <g>
      <title>Layer 1</title>
      <circle class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#6fdb6f" fill="none"/>
     </g>
    </svg>
</div>

<div class="item css">
    <h2>CSS</h2>
    <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
     <g>
      <title>Layer 1</title>
      <circle class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#69aff4" fill="none"/>
     </g>
    </svg>
</div>

version JSFiddle


Voici une version avec des cercles d'arrière-plan comme demandé dans les commentaires:

.item {
    position: relative;
    float: left;
}

.item h2 {
    text-align:center;
    position: absolute;
    line-height: 125px;
    width: 100%;
}

svg {
   -webkit-transform: rotate(-90deg);
    transform: rotate(-90deg);
}

.circle_animation {
  stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
  stroke-dashoffset: 440;
}

.html .circle_animation {
    -webkit-animation: html 1s ease-out forwards;
    animation: html 1s ease-out forwards;
}

.css .circle_animation {
    -webkit-animation: css 1s ease-out forwards;
    animation: css 1s ease-out forwards;
}

@-webkit-keyframes html {
  to {
    stroke-dashoffset: 80; /* 50% would be 220 (half the initial value specified above) */
  }
}

@keyframes html {
  to {
    stroke-dashoffset: 80;
  }
}

@-webkit-keyframes css {
  to {
    stroke-dashoffset: 160;
  }
}

@keyframes css {
  to {
    stroke-dashoffset: 160;
  }
}
<div class="item html">
    <h2>HTML</h2>
    <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
     <g>
      <title>Layer 1</title>
      <circle r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#f2f2f2" fill="none"/>
      <circle class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#6fdb6f" fill="none"/>
     </g>
    </svg>
</div>

<div class="item css">
    <h2>CSS</h2>
    <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
     <g>
      <title>Layer 1</title>
      <circle r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#f2f2f2" fill="none"/>
      <circle class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#69aff4" fill="none"/>
     </g>
    </svg>
</div>

Comment ça marche?

stroke-dasharray est utilisé pour définir le "modèle" utilisé par une ligne pointillée ( MDN ). En fournissant une valeur unique, vous créez un motif avec un tiret de 440 pixels et un espace de 440 pixels. (440px est à peu près la circonférence du cercle).

stroke-dashoffset déplace efficacement le point de départ du motif de tiret ( MDN ).

UNE dash-offset sur 220 (la moitié du stroke-dasharray) produirait un demi-cercle. 110 = quart de cercle, etc.

35
Turnip

j'ai écrit ceci comme une réponse de commentaire mais c'était trop long:

hm ... eh bien, voici un violon pour le deuxième cercle http://jsfiddle.net/LgtV2/ .... il a 3 parties de tarte. le premier cercle (100%) comprend 5 parties. vous devriez jouer avec le violon pour apprendre comment il fonctionne et ainsi vous pouvez le reproduire. Je n'ai jamais fait cela auparavant et je regarde simplement le lien publié par San, mais il semble que cela utilise simplement plusieurs Divs avec le css3 TRANSFORM pour former les courbes et les pseudo-sélecteurs: avant et: après pour les animations. Les animations se produisent pendant le chargement de la page elle-même ... EG:: avant le chargement de div1, il a une transformation de 5, il se charge et a une transformation de 8,: après le chargement, il a une transformation de 11.

code:

<div class="half_pie">
    <div class="half_part_pie_one half_bar_color half_percentage" data-percentage="35"></div>
    <div class="half_part_pie_two"></div>
    <div class="half_part_pie_three"></div> <span class="half_pie_icon iconfont-Android"></span>

</div>

/*percentage STEPS (do not touch)*/
 .full_percentage[data-percentage="100"] {
    -webkit-transform: rotate(180deg);
    -moz-transform: rotate(180deg);
    -o-transform: rotate(180deg);
    transform: rotate(180deg);
}
.full_percentage[data-percentage="95"] {
    -webkit-transform: rotate(170deg);
    -moz-transform: rotate(170deg);
    -o-transform: rotate(170deg);
    transform: rotate(170deg);
}
.full_percentage[data-percentage="90"] {
    -webkit-transform: rotate(155deg);
    -moz-transform: rotate(155deg);
    -o-transform: rotate(155deg);
    transform: rotate(155deg);
}
.full_percentage[data-percentage="85"] {
    -webkit-transform: rotate(125deg);
    -moz-transform: rotate(125deg);
    -o-transform: rotate(125deg);
    transform: rotate(125deg);
}
.full_percentage[data-percentage="80"] {
    -webkit-transform: rotate(110deg);
    -moz-transform: rotate(110deg);
    -o-transform: rotate(110deg);
    transform: rotate(110deg);
}
.full_percentage[data-percentage="75"] {
    -webkit-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    transform: rotate(90deg);
}
.full_percentage[data-percentage="70"] {
    -webkit-transform: rotate(70deg);
    -moz-transform: rotate(70deg);
    -o-transform: rotate(70deg);
    transform: rotate(70deg);
}
.full_percentage[data-percentage="65"] {
    -webkit-transform: rotate(55deg);
    -moz-transform: rotate(55deg);
    -o-transform: rotate(55deg);
    transform: rotate(55deg);
}
.full_percentage[data-percentage="60"] {
    -webkit-transform: rotate(35deg);
    -moz-transform: rotate(35deg);
    -o-transform: rotate(35deg);
    transform: rotate(35deg);
}
.full_percentage[data-percentage="55"] {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    transform: rotate(20deg);
}
.full_percentage[data-percentage="50"] {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
}
.half_percentage[data-percentage="50"] {
    -webkit-transform: rotate(180deg);
    -moz-transform: rotate(180deg);
    -o-transform: rotate(180deg);
    transform: rotate(180deg);
}
.half_percentage[data-percentage="45"] {
    -webkit-transform: rotate(170deg);
    -moz-transform: rotate(170deg);
    -o-transform: rotate(170deg);
    transform: rotate(170deg);
}
.half_percentage[data-percentage="40"] {
    -webkit-transform: rotate(155deg);
    -moz-transform: rotate(155deg);
    -o-transform: rotate(155deg);
    transform: rotate(155deg);
}
.half_percentage[data-percentage="35"] {
    -webkit-transform: rotate(125deg);
    -moz-transform: rotate(125deg);
    -o-transform: rotate(125deg);
    transform: rotate(125deg);
}
.half_percentage[data-percentage="30"] {
    -webkit-transform: rotate(110deg);
    -moz-transform: rotate(110deg);
    -o-transform: rotate(110deg);
    transform: rotate(110deg);
}
.half_percentage[data-percentage="25"] {
    -webkit-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    transform: rotate(90deg);
}
.half_percentage[data-percentage="20"] {
    -webkit-transform: rotate(70deg);
    -moz-transform: rotate(70deg);
    -o-transform: rotate(70deg);
    transform: rotate(70deg);
}
.half_percentage[data-percentage="15"] {
    -webkit-transform: rotate(55deg);
    -moz-transform: rotate(55deg);
    -o-transform: rotate(55deg);
    transform: rotate(55deg);
}
.half_percentage[data-percentage="10"] {
    -webkit-transform: rotate(35deg);
    -moz-transform: rotate(35deg);
    -o-transform: rotate(35deg);
    transform: rotate(35deg);
}
.half_percentage[data-percentage="5"] {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    transform: rotate(20deg);
}
.half_percentage[data-percentage="0"] {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
}
/*
 *
 * THE SECOND EXAMPLE
 * the second example for a max percentuage of 50% in this case
 *
 */

/*COLOR and STYLES (note: you can use gradients for the class full_bar_color)*/
 .half_bar_color {
    background: #3498db;
}
/*start chart pie code*/
 .half_pie {
    position: relative;
    width: 200px;
    height: 200px;
    margin: 0 auto;
    background: #fff;
    -webkit-border-radius: 100%;
    -moz-border-radius: 100%;
    -o-border-radius: 100%;
    border-radius: 100%;
}
/*the background white circular color*/
 .half_pie:before {
    content:'';
    display: block;
    position: absolute;
    z-index: -1;
    width: 220px;
    height: 220px;
    top: -10px;
    left: -10px;
    background: #fff;
    -webkit-border-radius: 100%;
    -moz-border-radius: 100%;
    -o-border-radius: 100%;
    border-radius: 100%;
}
/*color white #fff to fix the rendering problem*/
 .half_pie:after {
    content:'';
    display: block;
    position: absolute;
    z-index: 10;
    width: 198px;
    height: 198px;
    top: 1px;
    left: 1px;
    -webkit-box-shadow: 0px 0px 0px 2px #fff, inset 0 0 5px rgba(0, 0, 0, 0.1);
    -moz-box-shadow: 0px 0px 0px 2px #fff, inset 0 0 5px rgba(0, 0, 0, 0.1);
    box-shadow: 0px 0px 0px 2px #fff, inset 0 0 5px rgba(0, 0, 0, 0.1);
    -webkit-border-radius: 100%;
    -moz-border-radius: 100%;
    -o-border-radius: 100%;
    border-radius: 100%;
}
/*the icon*/
 span.half_pie_icon {
    position: absolute;
    z-index: 5;
    top: 25px;
    left: 25px;
    width: 150px;
    height: 150px;
    font-size: 3em;
    line-height: 150px;
    text-align: center;
    color: #e0e0e0;
    background: #fff;
    -webkit-box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);
    -moz-box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);
    box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);
    -webkit-border-radius: 100%;
    -moz-border-radius: 100%;
    -o-border-radius: 100%;
    border-radius: 100%;
}
/*ONE*/
 .half_part_pie_one {
    position: absolute;
    z-index: 1;
    width: 100%;
    height: 100%;
    -webkit-border-radius: 100%;
    -moz-border-radius: 100%;
    -o-border-radius: 100%;
    border-radius: 100%;
    clip: rect(0px 100px 200px 0px);
}
/*TWO*/
 .half_part_pie_two {
    position: absolute;
    z-index: 2;
    width: 100%;
    height: 100%;
    background: #fff;
    -webkit-border-radius: 100%;
    -moz-border-radius: 100%;
    -o-border-radius: 100%;
    border-radius: 100%;
    clip: rect(0px 100px 200px 0px);
}
/*THREE*/
 .half_part_pie_three {
    position: absolute;
    z-index: 3;
    width: 100%;
    height: 100%;
    background: #fff;
    -webkit-border-radius: 100%;
    -moz-border-radius: 100%;
    -o-border-radius: 100%;
    border-radius: 100%;
    clip: rect(0px 200px 200px 100px);
    -webkit-animation: half_third 4s linear;
    -moz-animation: half_third 4s linear;
    -o-animation: half_third 4s linear;
    animation: half_third 4s linear;
    opacity: 0;
}
/*THIRD animation*/
 @-webkit-keyframes half_third {
    0% {
        opacity: 1;
        -webkit-transform: rotate(0deg);
    }
    100% {
        opacity: 1;
        -webkit-transform: rotate(180deg);
    }
}
@-moz-keyframes half_third {
    0% {
        opacity: 1;
        -moz-transform: rotate(0deg);
    }
    100% {
        opacity: 1;
        -moz-transform: rotate(180deg);
    }
}
@-o-keyframes half_third {
    0% {
        opacity: 1;
        -o-transform: rotate(0deg);
    }
    100% {
        opacity: 1;
        -o-transform: rotate(180deg);
    }
}
@keyframes half_third {
    0% {
        opacity: 1;
        transform: rotate(0deg);
    }
    100% {
        opacity: 1;
        transform: rotate(180deg);
    }
}
8
user3037493

J'ai modifié un extrait que j'ai trouvé sur le Web pour créer un graphique en beignet simple en utilisant uniquement HTML et CSS, voici le résultat:

.block {
  margin: 25px 25px 0 0;
  background: #394264;
  border-radius: 5px;
  float: left;
  width: 300px;
  overflow: hidden;
}

.donut-chart-block {
  overflow: hidden;
}

.donut-chart {
  position: relative;
  width: 200px;
  height: 200px;
  margin: 2rem auto;
  border-radius: 100%
}

.donut-chart .center {
  background: #394264;
  position: absolute;
  top: 30px;
  left: 30px;
  height: 140px;
  width: 140px;
  border-radius: 70px;
}

.clip {
  border-radius: 50%;
  clip: rect(0px, 200px, 200px, 100px);
  height: 100%;
  position: absolute;
  width: 100%;
}

.item {
  border-radius: 50%;
  clip: rect(0px, 100px, 200px, 0px);
  height: 100%;
  position: absolute;
  width: 100%;
  font-family: monospace;
  font-size: 1.5rem;
}

#section1 {
  transform: rotate(0deg);
}

#section1 .item {
  background-color: #E64C65;
  transform: rotate(76deg);
}

#section2 {
  transform: rotate(76deg);
}

#section2 .item {
  background-color: #11A8AB;
  transform: rotate(140deg);
}

#section3 {
  transform: rotate(215deg);
}

#section3 .item {
  background-color: #4FC4F6;
  transform: rotate(113deg);
}

#section4 {
  transform: rotate(-32deg);
}

#section4 .item {
  background-color: #FCB150;
  transform: rotate(32deg);
}
<div class="container">
  <div class="donut-chart-block block">
    <div class="donut-chart">
      <div id="section1" class="clip">
        <div class="item" data-rel="21"></div>
      </div>
      <div id="section2" class="clip">
        <div class="item" data-rel="39"></div>
      </div>
      <div id="section3" class="clip">
        <div class="item" data-rel="31"></div>
      </div>
      <div id="section4" class="clip">
        <div class="item" data-rel="9"></div>
      </div>
      <div class="center"></div>
    </div>
  </div>
</div>

Décidé de le poster ici comme alternative aux autres réponses. À votre santé!

Dans le cas où vous devez créer une animation de graphique en anneau (juste du CSS simple) et également besoin de plusieurs couleurs pour cela, vérifiez l'exemple de codepen que j'ai créé.

http://codepen.io/hilar47/pen/RprXev

<div class="container">
  <div class="donut-chart-block block"> 
    <div class="donut-chart">
        <div id="part1" class="portion-block"><div class="circle"></div></div>
        <div id="part2" class="portion-block"><div class="circle"></div></div>
        <div id="part3" class="portion-block"><div class="circle"></div></div>
        <p class="center"></p>        
    </div>
3
Hilario Goes

Cette réponse n'est possible qu'en raison de la réponse de Turnip, mais j'ai apporté quelques modifications importantes, et je vais également expliquer comment cela fonctionne:

.donutContainer {
    position: relative;
    float: left;
}

.donutContainer h2 {
    text-align:center;
    position: absolute;
    line-height: 125px;
    width: 100%;
}

svg {
    transform: rotate(-90deg);
}

.donut {
  stroke-dasharray: 440;
  -webkit-animation: donut 1s ease-out forwards;
  animation: donut 1s ease-out forwards;
}

@-webkit-keyframes donut {
  from {
    stroke-dashoffset: 440;
  }
}

@keyframes donut {
  from {
    stroke-dashoffset: 440;
  }
}
<div class="donutContainer css">
    <h2>donut</h2>
    <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
     <g>
      <title>Layer 1</title>
      <circle id="circle" style="stroke-dashoffset: 160;/* 160 of 440 */" class="donut" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#69aff4" fill="none"/>
     </g>
    </svg>
</div>
<div class="donutContainer css">
    <h2>donut 2</h2>
    <svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
     <g>
      <title>Layer 1</title>
      <circle id="circle" style="stroke-dashoffset: 220;/* 220 of 440 */" class="donut" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#FEC007" fill="none"/>
     </g>
    </svg>
</div>

Étant donné que l'animation utilise from au lieu de to pour créer l'animation, les navigateurs qui ne prennent pas en charge l'animation afficheront le graphique en anneau complet, au lieu de pas du tout. Cela permet également de changer la partie colorée du graphique en anneau avec du CSS juste en ligne, et la même animation CSS unique peut fonctionner pour n'importe quel nombre des graphiques en anneau.

Une explication pour le truc svg:

stroke-dasharray: Dans ce cas, essentiellement la circonférence totale du cercle.

stroke-dashoffset: la partie du cercle colorée. Zéro (0) signifie tout coloré (100%), 440 (ou ce que vous définissez la circonférence) pour rien colorié (0%)

Attributs sur l'élément circle:

r: rayon du cercle

cx: "centre X". le centre du cercle (coordonnée X en bas à gauche de l'élément svg)

cy: "centre Y". le centre du cercle (coordonnée Y en bas à gauche de l'élément svg)

stroke-width: largeur du trait qui dessinera le beignet

stroke: couleur du beignet

2
Skeets