简单的SVG CSS进度圆形。

7

我正在寻找一种实现简单的进度圆形(静态)而不需要动画效果的方法。我发现的例子中,百分比的偏移量非常不同,例如下面的示例。如何使我的进度圆以这样的方式制作,即如果我提供50%的偏移量,则它恰好是50%(半满的状态)?

.u-absoluteCenter {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
}
.u-flexCenter {
  display: flex;
  align-items: center;
  justify-content: center;
}
.u-offscreen {
  position: absolute;
  left: -999em;
}
.demo {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.progress {
  transform: rotate(-90deg);
}
.progress__value {
  stroke-dasharray: 0;
  stroke-dashoffset: 0;
}
@-webkit-keyframes progress {
  from {
    stroke-dashoffset: 339.292;
  }
  to {
    stroke-dashoffset: 0;
  }
}
@keyframes progress {
  from {
    stroke-dashoffset: 339.292;
  }
  to {
    stroke-dashoffset: 0;
  }
}
<svg width="120" height="120" viewBox="0 0 120 120">
    <circle cx="60" cy="60" r="54" fill="none" stroke="#e6e6e6" stroke-width="12" />
    <circle cx="60" cy="60" r="54" fill="none" stroke="#f77a52" stroke-width="12"
        stroke-dasharray="339.292" stroke-dashoffset="339.292" />
</svg>


对于25%,请尝试使用stroke-dasharray =“ 84.823 254.469”,其中84.823表示路径长度(339.292)的25%,而间隙(254.469)表示75%。 - enxaneta
2个回答

20

您可以利用SVG属性来设置路径长度,而不必计算它。

pathLength可以将长度设置为您所需的任何值...比如说100,用于进度条。

pathLength属性允许作者指定路径的总长度(以用户单位)。然后,通过使用比率pathLength /(路径长度的计算值)缩放所有距离计算,将浏览器的距离计算与作者的距离计算进行校准。

pathLength="100"

那么您可以将 stroke-dasharray 设置为100,然后根据需要调整 stroke-dashoffset ...

::root {
  --val: 0;
}

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

.percent {
  stroke-dasharray: 100;
  stroke-dashoffset: calc(100 - var(--val));
}

.fifty {
  --val: 50;
}

.sixty {
  --val: 60;
}

.ninety {
  --val: 90;
}
<svg width="120" height="120" viewBox="0 0 120 120">
    <circle cx="60" cy="60" r="54" fill="none" stroke="#e6e6e6" stroke-width="12" />
    <circle class="percent fifty" cx="60" cy="60" r="54" fill="none" stroke="#f77a52" stroke-width="12" pathLength="100" />
</svg>

<svg width="120" height="120" viewBox="0 0 120 120">
    <circle cx="60" cy="60" r="54" fill="none" stroke="#e6e6e6" stroke-width="12" />
    <circle class="percent sixty" cx="60" cy="60" r="54" fill="none" stroke="#f77a52" stroke-width="12" pathLength="100" />
</svg>


<svg width="120" height="120" viewBox="0 0 120 120">
    <circle cx="60" cy="60" r="54" fill="none" stroke="#e6e6e6" stroke-width="12" />
    <circle class="percent ninety" cx="60" cy="60" r="54" fill="none" stroke="#f77a52" stroke-width="12" pathLength="100" />
</svg>


但是这只提供了3个值(50、60、90),我认为OP需要0-100之间的任何值。这是否适用? - Saif
这些值仅用于演示目的。调整数值非常简单。 - Paulie_D
好的。你能解释一下如何从HTML代码中提供一个值吗?比如26%。 - Saif
就像这样 @Saif https://codepen.io/andywebo/pen/gORyOYQ ...只需在style属性中内联执行计算。 - Andyweb
刚刚注意到在移动版Safari和Chrome(iOS上)中,stroke-dashoffset内的calc(100-x)值无法正常工作。必须使用结果数字代替。 - Andyweb

5
正如Paulie所说,pathLength是进度圆的关键。
现代JavaScript Web组件(JSWC在所有现代浏览器中都受支持)可用于创建可重复使用的HTML元素。
 <svg-progress-circle percent="30"></svg-progress-circle>
 <svg-progress-circle percent="20" color="blue"></svg-progress-circle>
 <svg-progress-circle percent="80" color="gold"></svg-progress-circle>

为了交互式演示目的,添加了一个范围输入。

百分比是元素上的属性,您可以使用类似以下代码进行设置:

    document.getElementById("Slider1").percent = <PERCENTAGE>;

如果您不想要一个虚线灰色的实心圆,请从pathLenght=120 path中删除虚线设置。

我使用了path而不是重叠的circles,因为在一些其他设置下,几乎相同的代码可以创建饼图。

<style>
  svg { width: 150px; background: teal }
  svg-progress-circle[percent="100"] path { stroke: green }
</style>

<svg-progress-circle percent="30"></svg-progress-circle>
<svg-progress-circle percent="20" color="blue"></svg-progress-circle>
<svg-progress-circle percent="80" color="gold"></svg-progress-circle>

<script>
  customElements.define("svg-progress-circle", class extends HTMLElement {
    connectedCallback() {
      let d = 'M5,30a25,25,0,1,1,50,0a25,25,0,1,1,-50,0'; // circle
      this.innerHTML = 
      `<input type="range" min="0" max="100" step="10" value="30"`+ // delete 2 lines
      ` oninput="this.parentNode.percent=this.value" /><br>`+ // just for demo
      
      `<svg viewBox="0 0 60 60">
       <path stroke-dasharray="10 2"   stroke-dashoffset="-19" 
             pathlength="120" d="${d}" fill="grey" stroke="lightgrey" stroke-width="5"/>
       <path stroke-dasharray="30 70" stroke-dashoffset="-25" 
             pathlength="100" d="${d}" fill="none" 
             stroke="${this.getAttribute("color")||"red"}" stroke-width="5"/>
       <text x="50%" y="57%" text-anchor="middle">30%</text></svg>`;
       
      this.style.display='inline-block';
      this.percent = this.getAttribute("percent");
    }
    set percent(val = 0) {
      this.setAttribute("percent", val);
      let dash = val + " " + (100 - val);
      this.querySelector("path+path").setAttribute('stroke-dasharray', dash);
      this.querySelector("text").innerHTML = val + "%";
      this.querySelector("input").value = val;
    }
  })
</script>

注意:我正在开发一个完整的Web组件,可以制作饼图和漂亮的进度圆形,例如:

但是,这只是众多副业之一... HTML示例和混淆的源代码可在https://pie-meister.github.io/上找到。


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