Html 圆形百分比进度条

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29350504/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 03:44:46  来源:igfitidea点击:

Circular percent progress bar

htmlcsssvgcss-shapes

提问by dhrm

I would like to have an percent circle indicator on my site:

我想在我的网站上有一个百分比圆圈指示器:

Radial progress bar mockup

径向进度条模型

In this case it's showing 75%. How should this be done? I have the yellow circle in a image-file, but if it's easier to, some how, do it all using CSS, that's okay with me.

在这种情况下,它显示 75%。这应该怎么做?我在图像文件中有黄色圆圈,但是如果使用 CSS 更容易(以某种方式)完成所有操作,那对我来说没问题。

回答by web-tiki

Considering the shape of the progress bar (rounded end/start) I would suggest using SVG.

考虑到进度条的形状(圆形结束/开始),我建议使用 SVG。

DEMO: Radial progress bar

演示:径向进度条

Radial progress bar

径向进度条

In the following example, the progress is animated with the stroke-dasarrayattribute and the % numbers are incremented with jQuery:

在下面的例子中,进度是用stroke-dasarray属性动画的,% 数字用 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>



Unfortunatly IE doesn't support svg SMIL animations. To achieve the same result with IE support, you can use a library like snap.svg and animate the stroke-dasharrayattribute with JS :

不幸的是,IE 不支持 svg SMIL 动画。要在 IE 支持下实现相同的结果,您可以使用 snap.svg 之类的库并stroke-dasharray使用 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>

回答by DoctorDestructo

Pure HTML/CSS Solution

纯 HTML/CSS 解决方案

In short, I used the CSS border-radiusand z-indexproperties to create a white half circle layered beneath an orange center circle and orange outer ring. Initially, the half-circle is completely hidden behind an additional layer of orange on the left side, but its outer edge is gradually revealed as it rotates around the center axis (via CSS transform: rotate()), creating the appearance of a progress bar. Additional trickery is required once the progress bar passes the halfway point (see below the snippet for more info).

简而言之,我使用 CSSborder-radiusz-index属性创建了一个白色的半圆,位于橙色中心圆和橙色外环下方。最初,半圆完全隐藏在左侧的额外橙色层后面,但随着它围绕中心轴旋转(通过 CSS transform: rotate()),它的外边缘逐渐显露出来,从而形成进度条的外观。一旦进度条通过中间点,就需要额外的技巧(有关更多信息,请参阅下面的代码段)。

All of this was done with pure HTML and CSS, except the animation, which uses JavaScript. It may appear to require more code than the SVG-based solutions, but the markup is actually much simpler, which makes it a good alternative in my opinion.

所有这些都是用纯 HTML 和 CSS 完成的,除了使用 JavaScript 的动画。与基于 SVG 的解决方案相比,它似乎需要更多的代码,但标记实际上要简单得多,这使其成为我认为的一个不错的选择。

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>

Notice that the fiftyPlusclass is added to the container element once the progress bar reaches the halfway point. This adds a static progress bar to the right half of the circle. Without it, the progress will appear to drain out of the right side instead of filling in the left side.

请注意,fiftyPlus一旦进度条到达中间点,该类就会添加到容器元素中。这会在圆圈的右半部分添加一个静态进度条。没有它,进度似乎会从右侧排出,而不是填充在左侧。

回答by Persijn

Demo : CODEPEN

演示:CODEPEN

Here is my attempt at getting the percentage circle indicator:

这是我尝试获取百分比圆圈指标:

Path draws two arches and i set the stroke-dasharray. we don't really need to set the dasharray since we set that later with javascript.

Path 绘制了两个拱门,我设置了stroke-dasharray。我们真的不需要设置 dasharray,因为我们稍后会使用 javascript 设置它。



Html

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

Java脚本

  1. Get the path with #first path.
  2. Get the length of the dash-array: path.getTotalLength();
  3. Increase the dash-array until its full: setAttribute('stroke-dasharray', i+","+length);Where i is increased.
  4. Find out what percentage we are at: (count++/ticks)*100
  5. add the percentage to the svg text: text.innerHTML=(count/tick)*100
  1. 获取路径#first path
  2. 获取破折号数组的长度: path.getTotalLength();
  3. 增加 dash-array 直到它满:setAttribute('stroke-dasharray', i+","+length);i 增加的地方。
  4. 找出我们的百分比: (count++/ticks)*100
  5. 将百分比添加到 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>

回答by Dr.Darshan

Circular PercentProgress bar using 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>

See Demo :- http://codingflag.in/mysketch.php?sketch=9

见演示:- http://codingflag.in/mysketch.php?sketch=9

回答by Olen

Have you tried this?

你试过这个吗?

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

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

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