【问题标题】:Circular percent progress bar圆形百分比进度条
【发布时间】:2015-06-03 17:19:38
【问题描述】:

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

在这种情况下,它显示 75%。这应该怎么做?我在图像文件中有黄色圆圈,但如果它更容易,以某种方式,使用 CSS 完成这一切,我没关系。

【问题讨论】:

  • 我还没有任何代码:)
  • 看看这个只需下载 CSS 和 HTML here
  • 不要用图像构建圆圈。使用 CSS 很容易做到。

标签: html css svg css-shapes


【解决方案1】:

你试过了吗?

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

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

【讨论】:

    【解决方案2】:

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

    演示:Radial progress bar

    在下面的示例中,使用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:25%;}
    <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>

    不幸的是 IE 不支持 svg SMIL 动画。要在 IE 支持下实现相同的结果,您可以使用类似 snap.svg 的库并使用 JS 为 stroke-dasharray 属性设置动画:

    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:25%;}
    <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>

    【讨论】:

    • 这看起来很整洁。但由于某种原因,动画在 IE11 上对我不起作用(数量增加,但白条始终处于 100%)
    • @AlvaroMontoro 不幸的是,IE 不支持 svg SMIL 动画。但是您可以使用 snap.svg codepen.io/web-tiki/pen/qEGvMN?editors=101 之类的库来获得相同的结果,这适用于最新的 FF、chrome 和 IE。
    • @Alexandr_TT 感谢报告。我在 chrome 中看到了一个问题并添加了一个修复程序。你能确认它也适合你吗?如果没有,请告诉我您使用的是什么浏览器?
    • @web-tiki 感谢您的快速响应和解决方案!在修复之前,我检查过Chrome、Firefox、Opera发现问题,现在在这些浏览器上都可以!
    • @NajamUsSaqib 我建议你问另一个问题,因为它与这里提出的问题无关
    【解决方案3】:

    演示:CODEPEN

    这是我获取百分比圆圈指示器的尝试:

    Path 绘制了两个拱门,我设置了 stroke-dasharray。 我们真的不需要设置 dasharray,因为我们稍后会使用 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. #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>

    【讨论】:

    • 百分比指示器在 IE 中似乎不起作用,但周围的圆圈可以。任何人对如何解决这个问题有建议吗?
    【解决方案4】:

    纯 HTML/CSS 解决方案

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

    所有这些都是用纯 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>

    请注意,一旦进度条到达中点,fiftyPlus 类就会添加到容器元素中。这会在圆圈的右半边添加一个静态进度条。没有它,进度看起来会从右侧流出,而不是填充到左侧。

    【讨论】:

      【解决方案5】:

      圆形百分比进度条使用Canvas ...

      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>

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-22
        • 1970-01-01
        • 2012-12-23
        • 1970-01-01
        • 1970-01-01
        • 2010-11-22
        相关资源
        最近更新 更多