web-dev-qa-db-fra.com

Barre de progression en pourcentage circulaire

J'aimerais avoir un indicateur de cercle en pourcentage sur mon site:

Radial progress bar mockup

Dans ce cas, il affiche 75%. Comment faut-il procéder? J'ai le cercle jaune dans un fichier image, mais si c'est plus facile de faire tout cela en CSS, ça ne me dérange pas.

36
dhrm

Compte tenu de la forme de la barre de progression (fin/début arrondi), je suggère d'utiliser SVG.

DEMO: barre de progression radiale

Radial progress bar

Dans l'exemple suivant, la progression est animée par le stroke-dasarray attribut et les% nombres sont incrémentés avec jQuery:

var count = $(('#count'));
$({ Counter: 0 }).animate({ Counter: count.text() }, {
  duration: 5000,
  easing: 'linear',
  step: function () {
    count.text(Math.ceil(this.Counter)+ "%");
  }
});
body{text-align:center;font-family: 'Open Sans', sans-serif;}
svg{width:30%;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg id="animated" viewbox="0 0 100 100">
  <circle cx="50" cy="50" r="45" fill="#FDB900"/>
  <path fill="none" stroke-linecap="round" stroke-width="5" stroke="#fff"
        stroke-dasharray="251.2,0"
        d="M50 10
           a 40 40 0 0 1 0 80
           a 40 40 0 0 1 0 -80">
    <animate attributeName="stroke-dasharray" from="0,251.2" to="251.2,0" dur="5s"/>           
  </path>
  <text id="count" x="50" y="50" text-anchor="middle" dy="7" font-size="20">100%</text>
</svg>

Malheureusement IE ne prend pas en charge les animations svg SMIL. Pour obtenir le même résultat avec IE support, vous pouvez utiliser une bibliothèque comme snap.svg et animer le stroke-dasharray attribut avec JS:

var count = $(('#count'));
$({ Counter: 0 }).animate({ Counter: count.text() }, {
  duration: 5000,
  easing: 'linear',
  step: function () {
    count.text(Math.ceil(this.Counter)+ "%");
  }
});

var s = Snap('#animated');
var progress = s.select('#progress');

progress.attr({strokeDasharray: '0, 251.2'});
Snap.animate(0,251.2, function( value ) {
    progress.attr({ 'stroke-dasharray':value+',251.2'});
}, 5000);
body{text-align:center;font-family:sans-serif;}
svg{width:30%;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<svg id="svg" viewbox="0 0 100 100">
  <circle cx="50" cy="50" r="45" fill="#FDB900"/>
  <path fill="none" stroke-linecap="round" stroke-width="5" stroke="#fff"
        stroke-dasharray="1,250.2"
        d="M50 10
           a 40 40 0 0 1 0 80
           a 40 40 0 0 1 0 -80"/>
  <text x="50" y="50" text-anchor="middle" dy="7" font-size="20">1%</text>
</svg>
<svg viewbox="0 0 100 100">
  <circle cx="50" cy="50" r="45" fill="#FDB900"/>
  <path fill="none" stroke-linecap="round" stroke-width="5" stroke="#fff"
        stroke-dasharray="125.6,125.6"
        d="M50 10
           a 40 40 0 0 1 0 80
           a 40 40 0 0 1 0 -80"/>
  <text x="50" y="50" text-anchor="middle" dy="7" font-size="20">50%</text>
</svg>

<svg id="animated" viewbox="0 0 100 100">
  <circle cx="50" cy="50" r="45" fill="#FDB900"/>
  <path id="progress" stroke-linecap="round" stroke-width="5" stroke="#fff" fill="none"
        d="M50 10
           a 40 40 0 0 1 0 80
           a 40 40 0 0 1 0 -80">
  </path>
  <text id="count" x="50" y="50" text-anchor="middle" dy="7" font-size="20">100%</text>
</svg>
64
web-tiki

Solution Pure HTML/CSS

En bref, j'ai utilisé les propriétés CSS border-radius Et z-index Pour créer un demi-cercle blanc en couches sous un cercle central orange et un anneau extérieur orange. Initialement, le demi-cercle est complètement caché derrière une couche supplémentaire d'orange sur le côté gauche, mais son bord extérieur est progressivement révélé en tournant autour de l'axe central (via CSS transform: rotate()), créant l'apparence de une barre de progression. Une ruse supplémentaire est requise une fois que la barre de progression passe à mi-chemin (voir ci-dessous l'extrait de code pour plus d'informations).

Tout cela a été fait avec du HTML et du CSS purs, à l'exception de l'animation, qui utilise JavaScript. Cela peut sembler nécessiter plus de code que les solutions basées sur SVG, mais le balisage est en fait beaucoup plus simple, ce qui en fait une bonne alternative à mon avis.

function setProgress(elem, percent) {
  var
    degrees = percent * 3.6,
    transform = /MSIE 9/.test(navigator.userAgent) ? 'msTransform' : 'transform';
  elem.querySelector('.counter').setAttribute('data-percent', Math.round(percent));
  elem.querySelector('.progressEnd').style[transform] = 'rotate(' + degrees + 'deg)';
  elem.querySelector('.progress').style[transform] = 'rotate(' + degrees + 'deg)';
  if(percent >= 50 && !/(^|\s)fiftyPlus(\s|$)/.test(elem.className))
    elem.className += ' fiftyPlus';
}

(function() {
  var
    elem = document.querySelector('.circlePercent'),
    percent = 0;
  (function animate() {
    setProgress(elem, (percent += .25));
    if(percent < 100)
      setTimeout(animate, 15);
  })();
})();
.circlePercent {
  position: relative;
  top: 26px;
  left: 26px;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  background: orange;
}
.circlePercent:before,
.circlePercent > .progressEnd {
  position: absolute;
  z-index: 3;
  top: 2px;
  left: 45px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: white;
  -ms-transform-Origin: 3px 46px;
  transform-Origin: 3px 46px;
  content: "";
}
.circlePercent:after,
.circlePercent > .progress {
  position: absolute;
  -ms-transform-Origin: 48px 48px;
  transform-Origin: 48px 48px;
  z-index: 0;
  top: 0;
  left: 0;
  width: 48px;
  height: 96px;
  border-radius: 48px 0 0 48px;
  background: orange;
  content: "";
}
.circlePercent.fiftyPlus:after {
  background: white;
  -ms-transform: rotate(180deg);
  transform: rotate(180deg);
}
.circlePercent > .progress.progress {
  background: white;
}
.circlePercent > .counter {
  position: absolute;
  box-sizing: border-box;
  z-index: 2;
  width: 100px;
  height: 100px;
  margin-top: -2px;
  margin-left: -2px;
  border-radius: 50%;
  border: 4px solid orange;
}
.circlePercent > .counter:before {
  position: absolute;
  z-index: 1;
  top: 50%;
  margin-top: -13px;
  width: 100%;
  height: 26px;
  font-size: 26px;
  line-height: 26px;
  font-family: sans-serif;
  text-align: center;
  color: white;
  content: attr(data-percent) "%";
}
.circlePercent > .counter:after {
  position: absolute;
  width: 80px;
  height: 80px;
  top: 6px;
  left: 6px;
  border-radius: 50%;
  background: orange;
  content: "";
}
.circlePercent > .counter[data-percent="100"] {
  background: white;
}
<div class="circlePercent">
  <div class="counter" data-percent="0"></div>
  <div class="progress"></div>
  <div class="progressEnd"></div>
</div>

Notez que la classe fiftyPlus est ajoutée à l'élément conteneur une fois que la barre de progression atteint le point intermédiaire. Cela ajoute une barre de progression statique à la moitié droite du cercle. Sans cela, la progression semblera s'écouler du côté droit au lieu de remplir le côté gauche.

18
DoctorDestructo

Démo: CODEPEN

Voici ma tentative d'obtenir l'indicateur de cercle de pourcentage:

Path dessine deux arches et je mets le tracé en forme de tableau. nous n'avons pas vraiment besoin de définir le tableau de données car nous le définissons plus tard avec javascript.


Html

<svg class="circles" viewbox="0 0 200 200">
  <g id="first">
    <circle r="50" cx="100" cy="100" fill="#fb0"/>
    <path fill="none" 
          stroke-linecap="round"
          stroke-width="7" 
          stroke="#ffa"
          stroke-dasharray="250,250"
          d="M100 60 
             A1 1 0 0 1 100 140
             A1 1 0 0 1 100 60"/>
    <text class="circ-text"
          text-anchor="middle"
          x="100" y="100"
          font-size="12px"
          fill="#ffa"
          >percentage
    </text>
  </g>
</svg>

Javascirpt

  1. Obtenez le chemin avec #first path.
  2. Obtenez la longueur du tableau de bord: path.getTotalLength();
  3. Augmentez le tableau de bord jusqu'à ce qu'il soit plein: setAttribute('stroke-dasharray', i+","+length); Où i est augmenté.
  4. Découvrez à quel pourcentage nous en sommes: (count++/ticks)*100
  5. ajoutez le pourcentage au texte svg: text.innerHTML=(count/tick)*100

var path = document.querySelector('#first path');
var text = document.querySelector('#first .circ-text');
var length = path.getTotalLength();
var i = 0;
var count = 0;
var ticks = 50;
setInterval(function() {
  if (i < length+length/ticks) {
    path.setAttribute('stroke-dasharray', i+","+length);
    i+=length/ticks;
    text.innerHTML=Math.round((count++/ticks)*100);
  }

}, 100);
var path = document.querySelector('#first path');
var text = document.querySelector('#first .circ-text');
var length = path.getTotalLength();
var i = 0;
var count = 0;
var ticks = 50;
setInterval(function() {
  if (i < length+length/ticks) {
        path.setAttribute('stroke-dasharray', i+","+length);
    i+=length/ticks;
    text.innerHTML=Math.round((count++/ticks)*100);
  }
  
}, 100);
<svg class="circles" viewbox="0 0 500 200">
  <g id="first">
    <circle r="50" cx="100" cy="100" fill="#fb0" />
    <path fill="none" stroke-linecap="round" stroke-width="7" stroke="#ffa" stroke-dasharray="250,250" d="M100 60 A1 1 0 0 1 100 140
       A1 1 0 0 1 100 60" />
    <text class="circ-text" text-anchor="middle" x="100" y="100" font-size="12px" fill="#ffa">percentage</text>
  </g>
10
Persijn

Circulaire Pourcentage Barre de progression utilisant Canvas ...

Circular Loader

var ctx = document.getElementById('circularLoader').getContext('2d');
var al = 0;
var start = 4.72;
var cw = ctx.canvas.width;
var ch = ctx.canvas.height; 
var diff;
function progressSim(){
        diff = ((al / 100) * Math.PI*2*10).toFixed(2);
        ctx.clearRect(0, 0, cw, ch);
        ctx.lineWidth = 17;
        ctx.fillStyle = '#4285f4';
        ctx.strokeStyle = "#4285f4";
        ctx.textAlign = "center";
        ctx.font="28px monospace";
        ctx.fillText(al+'%', cw*.52, ch*.5+5, cw+12);
        ctx.beginPath();
        ctx.arc(100, 100, 75, start, diff/10+start, false);
        ctx.stroke();
        if(al >= 100){
                clearTimeout(sim);
            // Add scripting here that will run when progress completes
        }
        al++;
}
var sim = setInterval(progressSim, 50);
<div id="loader">
        <canvas id="circularLoader" width="200" height="200"></canvas>
</div>

Voir la démo: - http://codingflag.in/mysketch.php?sketch=9

6
Dr.Darshan

Avez-vous essayé cela?

<percent-display percent="75" side="" colors=""></percent-display>

Source: http://angularscript.com/angularjs-round-percentage-bar-directive-ngpercentdisplay/

3
Olen