【问题标题】:Circular progress show more than 100%循环进度显示超过100%
【发布时间】:2020-03-24 20:09:08
【问题描述】:

我在这篇文章中做了一个圆形图表: https://medium.com/@pppped/how-to-code-a-responsive-circular-percentage-chart-with-svg-and-css-3632f8cd7705

但是,我也尝试在其上显示高于 100% 的值(该图显示了当月与上一月的消费比较,有时它需要看起来像这样)。我尝试在第一个圆圈中添加另一个圆圈和不透明度,但看起来不太好。

我希望它看起来像这样:

<svg viewBox="0 0 36 36" class="circular-chart cons">
  <path class="circle-bg" d="M18 2.0845
        a 15.9155 15.9155 0 0 1 0 31.831
        a 15.9155 15.9155 0 0 1 0 -31.831" />
  <path class="circle-round" stroke-dasharray="100 100" 
        style="opacity: 0.9;" d="M33.9155 18
        a 15.9155 15.9155 0 0 1 -31.831 0
        a 15.9155 15.9155 0 0 1 31.831 0" />
  <path class="circle-round" stroke-dasharray="19 100" d="M33.9155 18
        a 15.9155 15.9155 0 0 1 -31.831 0
        a 15.9155 15.9155 0 0 1 31.831 0" />

  <text x="18" y="20.35" class="percentage cons-fill">119%</text>
</svg>
.circle-bg {
  fill: none;
  stroke: #ddd;
  stroke-width: 3.8;
}
.circle-round{
  fill: none;
  stroke-width: 2.8;
  stroke-linecap: round;
  animation: progress 1s ease-out forwards;
}
.circular-chart.cons .circle-round {
  stroke: $cons;
}
@keyframes progress {
  0% {
    stroke-dasharray: 0 100;
  }
}
.cons-fill {
  fill: $cons;
}

【问题讨论】:

  • 您好 Jakub,欢迎使用 stackoverflow :) 有必要包含与您的问题相关的 your 代码,以便我们知道如何为您提供帮助。您可以查看问题的预期内容here 此外,请将您的范围限制为每个帖子 1 个问题。就我而言,您能否详细说明超过 100% 的含义?
  • 您好,非常抱歉,抱歉。我添加了代码并删除了第二个问题。
  • 好的,看起来不错。我不确定您是否在谈论文本,或者您是否想要重复加载程序或其他东西(它只是无限循环)。我尝试查找并没有看到重复的问题,所以如果有人在星期六之前没有遇到这个问题,我会尝试回答。所以澄清一下,您不是在寻找一个无限循环样式的加载器like this,这实际上是一回事吗?你想要一个分层的进度表吗?没有 JavaScript?
  • 没有无限循环样式的加载器。这只是以 % 显示的两个值的静态比较。如果需要 JS,我愿意接受建议。我现在想在 中添加一条带有阴影的小线,如果值高于 100%,但到目前为止我没能做到。感谢您对该主题感兴趣。
  • 坦率地说,循环进度项在这里并不合适。它们不适用于 100% 以上的值。条形图会是更好的选择。

标签: css animation svg css-animations


【解决方案1】:

考虑一个解决方案 - 在不同的圆圈上使用两个动画。

两个动画都在点击 svg 画布begin="svg1.click"后开始
一、第一部动画作品id="an_red",一秒画红圈dur="1s"

第一个动画id="an_red"一整圈后,第二个动画id="an_green"被打开,它绘制整个绿色圆圈10个循环的红色圆圈填充动画。

请阅读下面代码中的cmets。

.circle-bg {
  fill: none;
  stroke: #ddd;
  stroke-width: 3.8;
}
.circle-red{
  fill: none;
  stroke-width: 2.8;
  stroke-linecap: round; 
  stroke:red;
  stroke-dasharray:0 100;
}
.circle-green{
  fill:none;
  stroke: yellowgreen;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray:0 100;   
}

#txt1 {
text-anchor:middle;
dominant-baseline:central;
font-size:6px;
fill:dodgerblue;
}
<svg id="svg1" width="80vw" height="80vh" viewBox="0 0 36 36" opacity="1" class="circular-chart cons">
<g id="gr1">  
  <!-- Gray circle  -->
   <path  class="circle-bg" d="M18 2.0845
        a 15.9155 15.9155 0 0 1 0 31.831
        a 15.9155 15.9155 0 0 1 0 -31.831" />
  
 		
   <path class="circle-red"    
        style="opacity: 0.5;" d="M33.9155 18
        a 15.9155 15.9155 0 0 1 -31.831 0
        a 15.9155 15.9155 0 0 1 31.831 0" >
    <!-- Red circle rotation animation    -->
   <animate
	  id="an_red"
	  attributeName="stroke-dasharray"
	  dur="1s"
	  values="0 100;100 0"
	  begin="svg1.click"
	  end="an_green.end-1s"
	  repeatCount="indefinite"
	  
	  restart="whenNotActive" />
	 </path>      
	<circle class="circle-green"   
        cx="17.8155" cy="17.8155" r="14" >
		<!-- Green circle rotation animation -->
      <animate
	    id="an_green"
		attributeName="stroke-dasharray"
		begin="svg1.click+1s"
		dur="10s"
		values="0 100; 100 0"
		repeatCount="1"
		
		restart="whenNotActive"/>
    </circle>	
   <text id="txt1" x="50%" y="50%"  >Click me
      <!-- Text fade animation -->
	<animate attributeName="opacity" begin="svg1.click" dur="1s" to="0" fill="freeze" restart="whenNotActive" />
   </text>  
 </g>   
     <animate xlink:href="#svg1" attributeName="opacity" values="1;0" begin="an_green.end" dur="1s" fill="freeze" />
</svg>

更新

考虑当圆圈位于另一个之上时的选项

底部圆圈负责显示填充 100% 的动画
较亮颜色的上圈负责填充剩余的 19%。

当第一个、下一个圆圈的动画结束时,这个圆圈的动画开始

  <!-- Animation filling a dark red circle by 19% -->
    <animate 
     id="an_dark_red"
     attributeName="stroke-dasharray"
     begin="an_red.end"
     dur="1s"
     values="0 100;19 81"
     fill="freeze"
     restart="whenNotActive"  />

.circle-bg {
  fill: none;
  stroke: #ddd;
  stroke-width: 3;
}
.circle-round{
  fill: none;
  stroke-width: 3;
  
  stroke-linecap: round;
  stroke-dasharray:0 100; 
  }
 #txt1 {
text-anchor:middle;
dominant-baseline:central;
font-size:8px;
fill:red;
opacity:0;
}
<svg id="svg1" height="80vh" viewBox="0 0 36 36" class="circular-chart cons" >
   <!-- gray circle background -->
  <path class="circle-bg"  class="circle-bg" d="M18 2.0845
        a 15.9155 15.9155 0 0 1 0 31.831
        a 15.9155 15.9155 0 0 1 0 -31.831" />

 <path id="red" class="circle-round" stroke="#FFB5B5"
      
         d="M33.9155 18
        a 15.9155 15.9155 0 0 1 -31.831 0
        a 15.9155 15.9155 0 0 1 31.831 0" > 
	
	<!-- Animation filling the red circle 100% -->
	<animate
	  id="an_red"
	  attributeName="stroke-dasharray"
	  begin="svg1.click"
	  dur="4s"
	  values="0 100;100 0"
	  fill="freeze"
	  repeatCount="1"
	  restart="whenNotActive"/>
   </path> 	
   
  <path id="dark_red"  class="circle-round"  stroke="red" 
        stroke-dasharray="0 100" 
        d="M33.9155 18
        a 15.9155 15.9155 0 0 1 -31.831 0
        a 15.9155 15.9155 0 0 1 31.831 0" >
	  
	  <!-- Animation filling a dark red circle by 19% -->
	<animate 
	 id="an_dark_red"
	 attributeName="stroke-dasharray"
	 begin="an_red.end"
	 dur="1s"
	 values="0 100;19 81"
	 fill="freeze"
	 restart="whenNotActive"  />
  </path> 
   
    <text id="txt1" x="50%" y="50%"  >119%
      <!-- The appearance of the text -->
	<animate attributeName="opacity" begin="an_dark_red.end" dur="1s" to="1" fill="freeze" restart="whenNotActive" />
   </text>  
 
</svg>

选项,CSS 动画进度等于 119%

#svg1 {
 opacity:1;
 height:90vh;
 animation: hide 1s ease-out 7s forwards;
 } 
 
 @keyframes hide {
  100% {
    opacity: 0;
  }
} 
 .circle-bg {
  fill: none;
  stroke: #ddd;
  stroke-width: 3;
}
.circle-round{
  fill: none;
  stroke-width: 3;
    stroke-linecap: round;
  stroke-dasharray:0 100; 
  } 
  
  #red {
  animation: progress 4s ease-out forwards;
  }
  
  @keyframes progress {
  100% {
    stroke-dasharray: 100 0;
  }
} 

#dark_red {
animation: progress2 1s ease-out 3.9s forwards;
}  

@keyframes progress2 {
  100% {
    stroke-dasharray: 19 81;
  }
} 
  
 #txt1 {
text-anchor:middle;
dominant-baseline:central;
font-size:8px;
fill:red;
opacity:0; 
animation: text_an 2s ease-out 5.1s forwards;
}   

@keyframes text_an {
  100% {
    opacity: 1;
  }
}
<svg id="svg1" height="30vh" viewBox="0 0 36 36" class="circular-chart cons" >
   <!-- gray circle background -->
  <path class="circle-bg"  class="circle-bg" d="M18 2.0845
        a 15.9155 15.9155 0 0 1 0 31.831
        a 15.9155 15.9155 0 0 1 0 -31.831" />

 <path id="red" class="circle-round" stroke="#FFB5B5"
      
         d="M33.9155 18
        a 15.9155 15.9155 0 0 1 -31.831 0
        a 15.9155 15.9155 0 0 1 31.831 0" > 
		
   </path> 	
   
  <path id="dark_red"  class="circle-round"  stroke="red" 
        stroke-dasharray="0 100" 
        d="M33.9155 18
        a 15.9155 15.9155 0 0 1 -31.831 0
        a 15.9155 15.9155 0 0 1 31.831 0" >
	 	 
  </path> 
   
    <text id="txt1" x="50%" y="50%"  >119%  </text>   
      
 
</svg>

进度等于 175% 的 CSS 动画选项

#svg1 {
 opacity:1;
 animation: hide 3s ease-out 10s forwards;
 } 
 
 @keyframes hide {
  100% {
    opacity: 0;
  }
} 
 .circle-bg {
  fill: none;
  stroke: #ddd;
  stroke-width: 3;
}
.circle-round{
  fill: none;
  stroke-width: 3;
    stroke-linecap: round;
  stroke-dasharray:0 100; 
  } 
  
  #red {
  animation: progress 4s ease-out forwards;
  }
  
  @keyframes progress {
  100% {
    stroke-dasharray: 100 0;
  }
} 

#dark_red {
animation: progress2 3s ease-out 3.9s forwards;
}  

@keyframes progress2 {
  100% {
    stroke-dasharray: 75 25;
  }
} 
  
 #txt1 {
text-anchor:middle;
dominant-baseline:central;
font-size:8px;
fill:#CB5CCB;
opacity:0; 
animation: text_an 2s ease-out 7s forwards;
}   

@keyframes text_an {
  100% {
    opacity: 1;
  }
}
<svg id="svg1" height="80vh" viewBox="0 0 36 36" class="circular-chart cons" >
   <!-- gray circle background -->
  <path class="circle-bg"  class="circle-bg" d="M18 2.0845
        a 15.9155 15.9155 0 0 1 0 31.831
        a 15.9155 15.9155 0 0 1 0 -31.831" />

 <path id="red" class="circle-round" stroke="#CBAACB"
      
         d="M33.9155 18
        a 15.9155 15.9155 0 0 1 -31.831 0
        a 15.9155 15.9155 0 0 1 31.831 0" > 
		
   </path> 	
   
  <path id="dark_red"  class="circle-round"  stroke="#CB5CCB" 
        stroke-dasharray="0 100" 
        d="M33.9155 18
        a 15.9155 15.9155 0 0 1 -31.831 0
        a 15.9155 15.9155 0 0 1 31.831 0" >
	 	 
  </path> 
   
    <text id="txt1" x="50%" y="50%"  >175%  </text>   
      
 
</svg>

注意

CSS 动画选项适用于包括 Edge 在内的所有现代浏览器

【讨论】:

  • 非常感谢您的反馈。很不错。 Look smil worksEdgeIE 之外的所有地方
  • 我应该添加它适用于新边缘(使用铬),但它仍处于测试阶段。在 UIX 方面我非常喜欢这个
  • @soulshined 添加了 CSS 动画的示例。适用于所有现代浏览器,包括 Edge
【解决方案2】:

问题是,除非你延长路径,否则你不能走得超过一个完整的圆圈。我同意这不是显示这些值的最佳工具,但您可以这样做:

:root{
  --cons: #00ff00;
  --atime: 1s;
}
.shade{
  fill: none;
  stroke: #002200;
  stroke-width: 2.8;
  /*stroke-linecap: round;*/
  animation: sprogress var(--atime) ease-out forwards;
}
.circle-bg {
  fill: none;
  stroke: #ddd;
  stroke-width: 3.8;
}
.circle-round{
  fill: none;
  stroke-width: 2.8;
  stroke-linecap: round;
  animation: progress var(--atime) ease-out forwards;
}
.circular-chart.cons .circle-round {
  stroke: var(--cons);
}
@keyframes sprogress {
  0% {
    stroke-dasharray: 0 0 4 146;
  }
}
@keyframes progress {
  0% {
    stroke-dasharray: 0 150;
  }
}
.cons-fill {
  fill: var(--cons);
  font-size: 30%;
}
<svg viewBox="0 0 36 36" class="circular-chart cons" height="100vh">
  <path class="circle-bg" d="M18 2.0845
        a 15.9155 15.9155 0 0 1 0 31.831
        a 15.9155 15.9155 0 0 1 0 -31.831" />
  <path class="circle-round" stroke-dasharray="119 31" d="M33.9155 18
        a 15.9155 15.9155 0 0 1 -31.831 0
        a 15.9155 15.9155 0 0 1 31.831 0
        a 15.9155 15.9155 0 0 1 -31.831 0 " />
  <path class="shade" stroke-dasharray="0 115 4 31" 
        style="opacity: 0.9;" d="M33.9155 18
        a 15.9155 15.9155 0 0 1 -31.831 0
        a 15.9155 15.9155 0 0 1 31.831 0
        a 15.9155 15.9155 0 0 1 -31.831 0                         " />

  <text x="18" y="20.35" class="percentage cons-fill">119%</text>
</svg>

这个想法是路径现在有 150 个单位。要标记路径的位置,您有一个类shade 的路径。如果您需要超过 150 个,则添加更多不断转动的 a 元素,然后计算您需要哪些 stroke-dasharray 值。

顺便说一句,如果你取消注释 shade 类中的 stroke-linecap,你会得到一个有趣的效果,因为 both 两端都会显示,独立于 stroke-dasharray。 p>

编辑评论后:

首先,重要的是要注意原始代码中的技巧是圆周的周长是 100。因此,每个弧有 50 个单位。关于stroke-dasharray 属性,您可以给它成对的短划线间隙值。如果这些值的总和等于弧的周长,您可以轻松控制破折号的位置和长度。对于shade 路径,您从0 0 4 146(无破折号、无间隙、4 个单位破折号、146 个单位间隙)到0 115 4 31(无破折号、115 个单位间隙、4 个单位破折号、31 个单位间隙)的动画)。这样,破折号总是有 4 个单位,结尾是 115 + 4 = 119 单位。这并不完美,因为起始值(破折号的结尾)不是 0,而是 4。效果几乎不明显,但可以通过两种方式修复:

  • 用破折号开头标记百分比(0 0 4 1460 119 4 27)。
  • 在开头扩展shade 路径,然后更改stroke-dasharray 值。例如,如果您在开始处添加另一个弧,则周长将为 200,并且值将从 0 46 4 150 变为 0 165 4 31

【讨论】:

  • (+) 可能有必要更详细地解释几对属性值是如何工作的。- ``stroke-dasharray: 0 0 4 146`
  • 我在答案中添加了策略说明。希望对您有所帮助。
  • 谢谢。我很清楚,可见扇区保持恒定长度4 在动画过程中改变了它前后的间隙,我们旋转了扇区。
猜你喜欢
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多