原文地址:https://segmentfault.com/a/1190000021878369
作者:Fw恶龙
本文首发于:思否
一、需求
- 根据0-1百分比显示进度条;
- 进度条需要有间隔;
- 进度条样式需要发光;
二、绘制进度条
方案一:使用path绘制圆弧
-
根据百分比(per),计算终点坐标:
var deg = 2 * Math.PI * per + Math.PI / 2; // 该百分比对应的角度 var y = Math.sin(deg) * this.data.radius + this.data.center.y; // 利用正弦函数计算出坐标值y var x = Math.cos(deg) * this.data.radius + this.data.center.x; // 利用余弦函数计算出坐标值x
-
根据百分比(per),求得需要绘制的是大角弧(1),还是小角弧(0),需要注意的是在绘制100%的圆弧即圆时,需要分成两段弧来绘制,即先绘制一个半圆,再绘制另一个半圆:
if (per >= 0 && per <= 0.5) { this.data.laf = 0; } else if (per > 0.5 && per < 1) { this.data.laf = 1; }
-
根据高亮部分与间隔部分所占百分比,设置stroke-dasharray属性(对于有需求2的需要这步操作):
this.data.perimeter = 2 * Math.PI * this.data.radius; // 圆形周长 $().css('stroke-dasharray', this.data.perStart * this.data.perimeter + " " + this.data.perEnd * this.data.perimeter);
方案二:使用circle绘制圆,配合stroke-dasharray属性绘制进度条效果
-
根据百分比(per),计算stroke-dasharray对应的值:
this.data.perimeter = 2 * Math.PI * this.data.radius; // 圆形周长 $().css('stroke-dasharray', this.data.perLen + " " + (this.data.perimeter - this.data.perLen););
-
根据百分比(per),计算stroke-dasharray对应的值(对于有需求2的需要这步操作):
this.perStartLen = this.data.perimeter * this.data.perStart;// 高亮部分长度 this.perEndLen = this.data.perimeter * this.data.perEnd; // 间隔部分长度 for(var i = 0; this.data.perLen > 0; i++) { if(i%2 == 0) { // 向stroke-dasharray添加高亮部分长度 if(this.data.perLen <= this.perStartLen) { // 若当前百分比落在高亮区域,则该间隔加上剩余的进度条高亮长度 this.data.strokeDasharray += this.data.perLen + ' ' + this.data.perLenRemain; this.data.perLen -= this.data.perLen; } else { // 否则,向stroke-dasharray添加间隔部分长度this.perStartLen this.data.strokeDasharray += this.perStartLen + ' '; this.data.perLen -= this.perStartLen; } } else { // 向stroke-dasharray添加间隔部分长度 if(this.data.perLen <= this.perEndLen) { // 若当前百分比落在间隔区域,则该间隔加上剩余的进度条长度 this.data.strokeDasharray += (this.data.perLen + this.data.perLenRemain) + ' '; this.data.perLen -= this.data.perLen; } else { // 否则,向stroke-dasharray添加间隔部分长度this.perEndLen this.data.strokeDasharray += this.perEndLen + ' '; this.data.perLen -= this.perEndLen; } } }
- 需要注意的是,对于没有需求2的进度条,可以为进度条添加动画效果;而对于有需求2的进度条动画效果未达到预期,有待深入研究;
三、添加样式
-
外发光
<svg id="cw_svg" filter="url(#f1)"> <defs> <filter id="f1"> <feGaussianBlur result="blurOut" in="SourceGraphic" stdDeviation="6" /> <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> </filter> </defs>
- 旋转svg容器:由于起点位置根据需求不同会在不同位置,这个角度计算不写在js里。
四、示例(源代码)
- 方案一|Svg Progress Bar By Path
- 方案二|Svg Progress Bar By Circle
- 注:对于没有需求2的将perEnd设置为0即可。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。