使用CSS逐步创建和填充圆弧 - 圆形进度条

5
我在CSS方面不是很擅长,所以我很难像进度条一样填充圆弧。
我想要实现这样的“进度”圆弧: enter image description here 我找到了这个链接:https://codepen.io/enslavedeagle/pen/AXzaKE
#arc,
#arc::before {
  display: block;
  box-sizing: border-box;
  border-radius: 100%;
  width: 100px;
  height: 100px;
  position: absolute;
  background-color: transparent;
  padding: 0;
  margin: 0;
}

#arc {
  border: solid #00BBEE 12px;
  clip: rect(0px, 100px, 50px, 0px);
  margin: 25px;
}

#arc::before {
  content: '';
  border: solid black 12px;
  top: -12px;
  left: -12px;
  clip: rect(0px, 100px, 50px, 0px);
  transform: rotate(-150deg);
  /* define the fill length, using the rotation above.
     from -180deg (0% fill) to 0deg (100% fill) */
  /* if you have a better solution to make thing like this 
     work, please let me know! :) */
}

我一直尝试着将它自定义为我想要的样子,但是一直没有成功:这里是链接:https://codepen.io/anon/pen/qpNrEP

有人能帮忙吗?也可以提供其他解决方案来实现这个目标。

感激不尽。

此致敬礼。


你可以使用jQuery还是只能使用CSS? - Alvarez
我可以使用Angular 4。 - Elmer Dantas
4个回答

7

您可以使用具有两个弧形的SVG,并将其叠加在一起,然后使用stroke-dash-array

svg {
  height: 90vh;
  margin: auto;
  display: block;
}

path {
  stroke-linecap: round;
  stroke-width: 2;
}

path.grey {
  stroke: lightgrey;
}

path.purple {
  stroke: purple;
  stroke-dasharray: calc(40 * 3.142 * 1.85);
  stroke-dashoffset: 20;
  /* adjust last number for variance */
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 100 100">
    <path class="grey" d="M40,90
             A40,40 0 1,1 60,90"
          style="fill:none;"/>
    <path class="purple" d="M40,90
             A40,40 0 1,1 60,90"
          style="fill:none;"/>
</svg>


这正是我在寻找的...现在我只需要将 stroke-dashoffset 的值映射到0-100%,以使进度条工作。我想点赞一千次!非常感谢!您介意解释一下 stroke-dasharray 的计算方式(calc(40 * 3.142 * 1.85))吗? - Elmer Dantas
这比听起来要复杂一些,因为您可能需要使用JS来确定实际的破折号数组和破折号偏移量。计算大致为(半径* Pi *任何范围)。但是,如果您对它粗略处理,它会出错。正如我所说,这些通常由JS管理。这只是演示概念。 - Paulie_D
我会使用Angular进行管理,没问题。 我只想知道如何绘制弧线并填充它(stroke-dasharray)。 我之所以问是因为我不习惯使用几何形状... 所以我不明白你是如何得出这个结果的,比如:为什么是1.85? 在计算公式中为什么要这样做? 如果可能的话,我们可以在聊天中讨论吗? 再次感谢。 - Elmer Dantas
你好,你能告诉我如何让进度条变大吗? - Milan Panic
尽管我也在想1.85(而半径乘以圆周率为40 * 3.142),但我发现calc(40 * 3.142 * 1.85 * (1 - <fraction>))可以填充一个便利的范围为0到1的<fraction>定义的分数。 - Falko
啊,需要1.85来获取整个弧的长度。完整圆形将是半径* pi * 2。但由于底部缺失,因此因子仅为1.85。细节取决于M40,90 A40,40 0 1,1 60,90如何结果成为一个圆弧。 - Falko

3

使用SVG是创建此类弧形的最佳方式。 以下是包含所有加载器迭代的解决方案:

.progress-wrapper {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: space-around;
}

path {
  stroke-linecap: round;
  stroke-width: 6;
}

.grey {
  stroke: #e5e5e5;
}

.red {
  stroke: #e33800;
  stroke-dasharray: 248;
  stroke-dashoffset: 240;
  /* adjust last number for variance */
}

.red-02 {
  stroke-dashoffset: 220;
}

.red-03 {
  stroke-dashoffset: 200;
}

.red-04 {
  stroke-dashoffset: 180;
}

.red-05 {
  stroke-dashoffset: 160;
}

.red-06 {
  stroke-dashoffset: 140;
}

.red-07 {
  stroke-dashoffset: 120;
}

.red-08 {
  stroke-dashoffset: 100;
}

.red-09 {
  stroke-dashoffset: 50;
}

.red-10 {
  stroke-dashoffset: 0;
}
<div class="progress-wrapper">
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-02" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-03" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-04" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-05" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-06" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-07" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-08" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-09" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-10" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
</div>

https://codepen.io/shalinigandhi/pen/mdmmwdV


0

我刚刚在Angular 2中创建了一个plnker,我认为这正是你想要的。

它使用变量来管理第二个弧形的填充:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 100 100">
    <path class="grey" d="M40,90 A40,40 0 1,1 60,90" style="fill:none;"/>
    <path [ngStyle]="{'stroke-dashoffset':percentPath}" class="blue" d="M40,90 A40,40 0 1,1 60,90" style="fill:none;"/>
</svg>

然后,在组件中,我调用一个函数,该函数获取滑块的值,最小值为0,最大值为100:

this.percentPath=(233-(V*2.33)); //233 is the maximun number stroke-dashoffset needs to disapear the second path 

https://plnkr.co/edit/KNPThi?p=info

来看一下吧!


谢谢,但是根据答案我已经创建了一个可以动态使用的组件。你可以在此链接 https://elmeerr.github.io/ng2-arc-progress-demo/ 进行查看。 - Elmer Dantas
酷!! 太棒了。我本来要做这个组件,但你已经完成了。谢谢! - Ricardo Del Rio
@ElmerDantas 你有没有尝试过在页面加载完成后将弧从0动画到相应的值?现在我遇到了这个问题。 - Ricardo Del Rio
我不确定是否理解正确,但是不需要使用从0到相应值的for循环,然后递增用作填充弧形进度的模型变量。 - Elmer Dantas

0

在这里没有找到我喜欢的答案后,我自己做了一些工作,并制作了一个Codepen,您可以使用它来制作进度条,输入为:应为100%的圆的度数,圆的半径和您要填充的百分比。 进度条示例(图像)

HTML:

<section class="stat" id="sectionId">
  <svg viewbox="0 0 100 100">
    <path class="bar" d="
    M 10, 50
    a 40,40 0 1,0 80,0
    a 40,40 0 1,0 -80,0
   "/>
    <path class="progress" d="
      M 10, 50
    a 40,40 0 1,0 80,0
    a 40,40 0 1,0 -80,0
    "/>
  </svg>

  <script type="text/javascript">
    _.makeProgressBar("01", 240, 40, 86);
  </script>
</section>

CSS:
.stat {
  width: 200px;
}

svg {
  display: block;
  transform-origin: center center;
  transform: rotate( 90deg );
}

path {
  stroke-linecap: round;
  stroke-width: 6px ;
  fill:none;
}

JS:

_ = {};

//this is a self executing function, it keeps the global namespace clean
(function(win, doc, helper){

  helper.makeProgressBar = function(id, totalDegrees, radius, percentage) {
    var section = doc.getElementById(id);
    var svg = section.children[0];
    var bar = svg.children[0];
    var progress = svg.children[1];

    if(percentage > 100){
        percentage = 100;
    }
    if(percentage < 0){
        percentage = 0;
    }

    var percentageDegrees = calculateDegreesFromPercentage(totalDegrees, percentage);

    var barDash = calculateDash(totalDegrees, radius);
    var barGap = calculateDash ( 360 - totalDegrees, radius) * 2;

    var progressDash = calculateDash(percentageDegrees, radius);
    var progressGap = calculateDash(360 - percentageDegrees, radius) * 2;

    var rotation = 0 - ((totalDegrees - percentageDegrees) / 2);

    bar.setAttribute("style", "stroke: #707070; fill: none; stroke-dasharray: " + barDash + " " + barGap + ";");
    progress.setAttribute("style", "stroke: #23CE39; fill: none; stroke-dasharray: " + progressDash + " " + progressGap + "; transform-origin: center center; transform: rotate("+ rotation +"deg)");
  }

  calculateDegreesFromPercentage = function(totalDegrees, percentage) {
    return totalDegrees/100*percentage;
  }

  calculateDash = function(degrees, radius) {
    return degrees * Math.PI / 180 * 0.5 * radius;
  }
})(window, document, _);

截图看起来很棒,但 Codepen 似乎无法工作。 - Christophe
@Christophe 对于回复慢的问题我很抱歉,我刚刚检查了一下,不知道为什么这个网站需要思考好几秒钟才能工作,但是它仍然可以正常工作,而我并没有做出任何更改。你按了让进度条出现的按钮吗? - mark-vandenberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接