《Radial progress indicator using CSS》,该文核心是用纯CSS来做一个环形的进度条。纯css的意思就是连百分比这种数字,都是css生成的。文章作者采取的方式是生成100个span标签,然后为这100个标签生成100段css代码(用less生成,代码量倒不大,只是生成的代码量会很大),不知道有没有更NB更省资源的css方案。
而我的需求很简单,只需要学习怎么画环进进度条即可,进度掌控当然得由js来通知(比如下载进度,或者音乐播放进度)
对E文没有恐惧感的话,建议直接看原作者的文,我这不是全文翻译,而是自己的练习。
注:为了方便,我只对chrome写了样式,所以如果要运行我在jsfiddle里面写的例子,最好选webkit系的浏览器
原作者讲解得很详细,我们直接跳过吧,自己学习css3关于动画的部分,总之,先成功一个例子再说:
<div class="radial-progress">
<div class="circle">
<div class="mask">
<div class="fill"></div>
</div>
</div>
</div>
一个容器,一个一环形元素,再加一个mask,和fill,后面介绍
为了直接在jsfiddle上使用,我也用less吧,毕竟只要一句js声明即可客户端解析(插一句,工程项目建议用sass,因为有compass这个库,大大减轻工作量)
@size:120px;
@bgcolor:#ddd;
@bgcolor1:#cc7;
@duration:1s;
*{margin:0;padding:0;}
.radial-progress{
margin:30px 50px;
position: relative;
.comm(){
width:@size;
height:@size;
position: absolute;
top:0;
left:0;
border-radius: 50%;
}
.circle{
.comm;
background: @bgcolor;
.mask{
clip:rect(0,@size,@size,@size/2);
.comm;
}
.fill{
background: @bgcolor1;
clip:rect(0,@size/2,@size,0);
transition:-webkit-transform @duration;.comm;}
}
}
$('head style[type="text/css"]').attr('type', 'text/less');
less.refreshStyles();
$(function(){
var m=$(".fill"),el=$("#deg").val(60),cur=$("#cur");
$("#start").click(function(){
var deg=el.val()||60;
m.css("transform","rotate("+deg+"deg)");
cur.text(deg);
el.val(Math.ceil(Math.random()*180));
});
$("#start").click();
});
上面的例子做完后,你应该发现这种转法,最多只能转180度啊!好吧,于是我们如法泡制,画一个左边的容j器和右边的色块:
<div class="radial-progress">
<div class="circle">
<div class="mask left">
<div class="fill"></div>
</div>
<div class="mask right">
<div class="fill"></div>
</div>
</div>
</div>
@size:120px;
@bgcolor:#ddd;
@bgcolor1:#cc7;
@duration:1s;
*{margin:0;padding:0;}
.radial-progress{margin:30px 50px; position: relative;
.comm(){
width:@size;height:@size;position: absolute;top:0;left:0;border-radius: 50%;
}
.circle{
background: @bgcolor;.comm;
.mask,.fill{.comm;}
.fill{
background: @bgcolor1;
transition:-webkit-transform @duration;
}
.left{
clip:rect(0,@size/2,@size,0);
.fill{clip:rect(0,@size,@size,@size/2);}
}
.right{
clip:rect(0,@size,@size,@size/2);
.fill{clip:rect(0,@size/2,@size,0);}
}
}
}
js不变,直接运行http://jsfiddle.net/walker/smMzz/1/
显然不是我们要的效果
这时作者做了大胆的改动,别的进度条方案我还没来得及研究,总之他这种是非常“别扭”的,管它呢,先实现,后面的就都不贴代码了,每一节后面都有我贴的jsfiddle的地址,可以直接去看源码。
.full
这个层整个蒙板也旋转同样的角度!【注意】,此时两个蒙板其实已经不重合了。这样,本来两个重叠的色块,因为某一个容器继续旋转了同样的角度,比如30度,视觉上就出现了60度范围的色块!至此已经大功告成,我们中间再添加一个跟底色一样的div把它变圆不就可以了吗?
对的,顺便还加了点内阴影外阴影,这样就有3D甜甜圈的效果了:http://jsfiddle.net/walker/smMzz/4/
如果要看代码,就注意一下,这一步只是添加了一个.inset
和一个.shadow
,对应的css看源码。
我们这里就不要3D了,简化一下,把3D啊,阴影啊,都去掉:http://jsfiddle.net/walker/smMzz/5/
至此,我参考的老外原文已经和我下面的东西不沾边了,感兴趣他怎么用纯css来实现动态进度条的可继续在原文观看,我这里基本上是js部分了,目的是让进度条响应当前进度。
.inset
里面,以百分号表示run
和process
方法,其中process
其实就是把前面onclick的内容给提取了出来,只需要传入一个100以内的数字上面的例子是模拟下载或者上传进度条。什么意思?不管是上传,还是下载,进度只是一个“状态”,你不能手动更改这个状态,而播放器则不同,你更改这进度条的百分比,应该能影响歌曲或影片从哪个时间点开始播放,因此,我们需要响应点击事件,同时还要会计算点击位置的角度:
.circle
作为点击事件的响应对象,因为不受.mask
和.fill
元素是否可见的影响。并把其鼠标状态改为手形.circle
上面,所以我们又要把.mask
和.fill
这两个层设为鼠标穿透(用pointer-events:none
实现),以免点击不到.circle
元素